4

I have JSON data that looks like this

{
    "latitude": 34.088051,
    "longitude": -118.296512,
    "timezone": "America/Los_Angeles",
    "daily": {
        "summary": "No precipitation throughout the week, with high temperatures rising to 92°F on Friday.",
        "icon": "clear-day",
        "data": [
            {
                "time": 1535266800,
                "summary": "Mostly cloudy in the morning.",
                "icon": "partly-cloudy-day",
                "sunriseTime": 1535289854,
                "sunsetTime": 1535336915,
                "moonPhase": 0.51}

I want to pull the time, summary, icon from this.

I create a class of type WeatherObject, but that's where I get stuck. How do I create the struct(s)? The keys are not snake cased or badly named so I think I can get away without using an enum to rename the variable names.

EDIT: Do - Catch falling through to catch. VC implements protocol. Data passed to protocol method prints in method implementation, but fails to process in do clause.

protocol NetworkingDelegate: AnyObject {
    func didGetResult(data: Data?) -> Void
}


class Networking: NSObject {

    var data: Data?
    weak var delegate: NetworkingDelegate?

    func makeAPIRequest(apiString: String) -> Void {
        guard let url: URL = URL(string: apiString) else{
            print("ERROR no URL")
            return
        }

        let urlRequest = URLRequest(url: url)

        let dataSession = URLSession.shared
        let dataTask = dataSession.dataTask(with: urlRequest) { (data, response, error) in

            guard error == nil else{
                print("ERROR found in networking call")
                print(error!)
                return
            }

            if data != nil{

                print("Data exists in networking")
                self.delegate?.didGetResult(data: data!)




            }else{
                print("ERROR: did not receive data")
            }
        }

        dataTask.resume()
    }


}

In ViewController

  func didGetResult(data: Data?) {



            do {

                if let dataObject = data{

                    let theString:NSString = NSString(data: dataObject, encoding: String.Encoding.ascii.rawValue)!
                    print(theString)
                }
                let newJSONDecoder = JSONDecoder()
                let weatherObject = try newJSONDecoder.decode(WeatherObj.self, from:data!)
                let dailyObject = weatherObject.daily
                let dataArray = dailyObject.data
                //LOOP THROUGH dataArray and get the required info
                for val in dataArray {
                    print("=======")
                    print(val.time)
                    print(val.summary)
                    print(val.icon)
                    print("=======")
                }
            } catch {
                print("error while parsing:\(error.localizedDescription)")
            }


        }

1 Answer 1

5

You can create the struct like this

struct WeatherObject: Codable {
  let latitude: Double
  let longitude: Double
  let timezone: String
  let daily: Daily
}

struct Daily: Codable {
    let summary: String 
    let icon: String
    let data: [Datum]
}

struct Datum: Codable {
    let time: Int
    let summary: String
    let icon: String
    let sunriseTime: Int
    let sunsetTime: Int
    let moonPhase: Double
}

Then you can parse it and get the required informations

do {
    let newJSONDecoder = JSONDecoder()
    let weatherObject = try newJSONDecoder.decode(WeatherObject.self, from: jsonData)
    let dailyObject = weatherObject.daily
    let dataArray = dailyObject.data
    //LOOP THROUGH dataArray and get the required info
    for val in dataArray {
        print("=======")
        print(val.time)
        print(val.summary)
        print(val.icon)
        print("=======")
    }
} catch {
    print("error while parsing:\(error.localizedDescription)")
}

Hope it helps

Sign up to request clarification or add additional context in comments.

7 Comments

Just to clarify, I create structs in my WeatherObject class that represent the JSON structure and the decoder references those to decode the data?
I'm getting a warning: 'catch' block is unreachable because no errors are thrown in 'do' block
You can define the struct for WeatherObject and add the variables I listed above and in your API response, i.e URLSession code, you can put the do use JSONDecoder and parse them as shown. See my edits.
The data exists in the code, but it falls through to the catch clause without calling the do clause code.
error while parsing:The data couldn’t be read because it is missing. I've checked prior to going into the do clause that the data is there, it exists. I calling a delegate method in the URLSession closure to call a method implementation in the VC to pass the data back to the VC. This seems to be fine because the data prints out before the do clause.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.