user8769899
user8769899

Reputation:

Working with JSON data retrieving into Swift data types

I'm trying to get data from a URL. It was successful. I can download and convert to a dictionary[String : Any] but response is in nested loops. I don't to how to retrieve. Can someone suggest how to get text and value in the response?

func getDataFromUrl() {
  let url = URL(string: "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&departure_time=1408046331&origins=37.407585,-122.145287&destinations=37.482890,-122.150235")
  let request = NSMutableURLRequest(url: url!)
  let session = URLSession.shared
  request.httpMethod = "GET"
  let dataTask = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
    do {
      let jsonData = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any]
      let destinationAddress  = jsonData!["destination_addresses"]
      print("Destination address \(String(describing: destinationAddress!))")
      let origin_addresses  = jsonData!["origin_addresses"]
      print("Origin_addresses \(String(describing: origin_addresses!))")
      let rows  = jsonData!["rows"]
      print("Rows  \(String(describing: rows!))")
      // Here I want to print text and value.

    } catch {
      // handle error
    }
  })
  dataTask.resume()
}

Upvotes: 0

Views: 186

Answers (3)

Gertjan.com
Gertjan.com

Reputation: 440

The above answers work, but in my opinion the more swiftier approach is to use Codable.

class MyResponseType:Codable {
    let destination_addresses:String
    let rows:[MyCustomRowData]
}

class MyCustomRowData:Codable {
    let elements:[MyCustomElementsData]
}

class MyCustomElementsData:Codable {
    // properties here
}

Doing this, parsing the json is done like this:

let response = try? JSONDecoder().decode(MyResponseType.self, from: data)

Where the data variable is just the retrieved Data object from the request.

Initially you have to set up some boilerplate code to replicate your expected data format, but working with it is really worth it (and it makes it highly testable).

When the decode succeeds you have a perfectly typed object, it can also have optionals. It just wont decode if fields are missing or of the wrong type (which is a good thing).

Upvotes: 1

User511
User511

Reputation: 1486

Use this code:

  let rows = jsonData["rows"] as! Array
  let element = rows[0] as! Dictionary
  let elementArray = element.value(forKey: "elements")
  let distance = elementArray[0].value(forKey: "distance")
  let text = distance.value(forKey: "text")
  print(text)
  let value = distance.value(forKey: "value")
  print(value)

Upvotes: 0

Dharmesh Kheni
Dharmesh Kheni

Reputation: 71852

Here is the way you can parse text and Value from response:

do{

            if let jsonData = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any] {

                if let destinationAddress = jsonData["destination_addresses"] as? [String] {
                    print(destinationAddress) //["1 Hacker Way, Menlo Park, CA 94025, USA"]
                }

                if let origin_addresses = jsonData["origin_addresses"] as? [String] {
                    print(origin_addresses) //["3251 Hillview Ave, Palo Alto, CA 94304, USA"]
                }

                if let rows = jsonData["rows"] as? [[String: AnyObject]] {
                    if rows.indices.contains(0) {
                        if let elements = rows[0]["elements"] as? [[String: AnyObject]] {
                            for element in elements {
                                if let duration = element["duration"] as? [String: AnyObject] {
                                    let text = duration["text"] as? String ?? ""
                                    print(text) //17 mins
                                    let value = duration["value"] as? Int ?? 0
                                    print(value) //1010
                                }

                                if let distance = element["distance"] as? [String: AnyObject] {
                                    let text = distance["text"] as? String ?? ""
                                    print(text) //7.2 mi
                                    let value = distance["value"] as? Int ?? 0
                                    print(value) //11555
                                }
                            }
                        }
                    }

                }
            }

        }catch{ //error handle

        }

Upvotes: 0

Related Questions