【问题标题】:How to retrieve specific data from JSON response?如何从 JSON 响应中检索特定数据?
【发布时间】:2019-01-12 14:11:59
【问题描述】:

目前,我正在使用 Google Maps 距离矩阵 API,并在运行以下代码时得到以下结果:

func configureRoute(origin:String,destination:String){
    let jsonURL = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=place_id:\(origin)&destinations=place_id:\(destination)&key=MYAPIKEY"
    guard let url = URL(string: jsonURL ) else {return}

    URLSession.shared.dataTask(with: url) { (data, response, err) in

        guard let data = data else {return}

        let dataAsString = String(data: data, encoding: .utf8)
        print(dataAsString)
        }.resume()
    }

这是结果:

Optional("{\n   \"destination_addresses\" : [ \"Pittsburgh, PA, USA\" ],\n   \"origin_addresses\" : [ \"Philadelphia, PA, USA\" ],\n   \"rows\" : [\n      {\n         \"elements\" : [\n            {\n               \"distance\" : {\n                  \"text\" : \"305 mi\",\n                  \"value\" : 490750\n               },\n               \"duration\" : {\n                  \"text\" : \"4 hours 48 mins\",\n                  \"value\" : 17257\n               },\n               \"status\" : \"OK\"\n            }\n         ]\n      }\n   ],\n   \"status\" : \"OK\"\n}\n")

但是,从这个结果中,我只想得到距离的持续时间,在这种情况下是 4 小时 48 分钟。我如何才能获得持续时间?

在尝试了一些建议后,我放置了我的 JSON url 以获取格式化的结构并得到以下结果:

struct Welcome: Codable {
let destinationAddresses, originAddresses: [String]
let rows: [Row]
let status: String

enum CodingKeys: String, CodingKey {
    case destinationAddresses = "destination_addresses"
    case originAddresses = "origin_addresses"
    case rows, status
}
}

struct Row: Codable {
let elements: [Element]
 }

struct Element: Codable {
let distance, duration: Distance
let status: String
}

struct Distance: Codable {
let text: String
let value: Int
 }

使用它,我实现了以下代码:

func configureRoute(origin:String,destination:String){
    let jsonURL = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=place_id:\(origin)&destinations=place_id:\(destination)&key=MYAPIKEY"
    guard let url = URL(string: jsonURL ) else {return}
    print(jsonURL)

    URLSession.shared.dataTask(with: url) { (data, response, err) in

        guard let data = data else {return}

        do{
            let route = try JSONDecoder().decode(Element.self, from: data)
            print (route.duration)
        }
        catch let jsonErr{

        }
        let dataAsString = String(data: data, encoding: .utf8)
//            print(dataAsString)
        }.resume()
}

但是我的 route.duration 的结果仍然没有。

【问题讨论】:

  • JSONSerialization, Codable,你有没有尝试解析 JSON?
  • 创建符合Decodable并对应接收到的JSON对象的结构体,然后使用JSONDecoder方法填充

标签: ios json swift4 google-distancematrix-api


【解决方案1】:
  1. 获取您的 JSON 响应并将其粘贴到以下在线 json 到 swift 结构转换器中。 JSON String to Swift struct converter

    {
    "name": "John",
    "age": 31,
    "city": "New York"
    }
    
  2. 现在复制生成的结构体。

    struct JSON: Codable {
     let name: String
     let age: Int
     let city: String
    }
    
  3. 解码您的数据响应。不要忘记尝试捕获和错误处理

    let jsonRespone:JSON = try JSONDecoder().decode(JSON.self, data);
    
  4. 现在您可以使用结构访问数据。如果您的 JSON 响应包含一些并不总是存在的信息(例如错误消息),只需将您的 JSON 结构或该特定键设为可选。

    let cityName:String = jsonResponse.city
    let age:Int = jsonResponse.age
    let name:String = jsonResponse.name
    

【讨论】:

  • 我在问题中添加了一些细节,并按照您的步骤操作,但是 JSON 响应有点奇怪。
  • 如果您将 jsonURL 粘贴到浏览器中,您通常会得到 json 字符串,您可以将其粘贴到在线转换器中。
  • 好的,我做了以下,仍然没有工作。我已经用我的结果更新了我的问题
  • 如果您从浏览器粘贴您的 json 字符串,我会查看它
  • 完成,我无法放置确切的字符串,因为它有我的 APIKey,但我已经粘贴了上面的结果。
【解决方案2】:

使用 SwiftyJSON:

导入SwiftyJSON

func configureRoute(origin:String,destination:String){
    let jsonURL = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=place_id:\(origin)&destinations=place_id:\(destination)&key=MYAPIKEY"
    guard let url = URL(string: jsonURL ) else {return}

    URLSession.shared.dataTask(with: url) { (data, response, err) in

        guard let data = data else {return}

        let dataAsString = String(data: data, encoding: .utf8)
        if let json = JSON(data: data){
            if let durationValue = json["rows"][0]["elements"][0]["duration"]["value"].int32 {
            //This is duration seconds, 17257
        }

        if let durationText = json["rows"][0]["elements"][0]["duration"]["text"].stringValue {
           //this is duration text, 4 hours 48 mins
        }
        print(dataAsString)
        }.resume()
    }

【讨论】:

  • 我收到 2 个错误“调用可以抛出,但它没有标记为 'try' 并且错误未处理”和“条件绑定的初始化程序必须是可选类型,而不是 JSON 类型”和它们都带有“if let json = JSON(data:data)
猜你喜欢
  • 2020-12-30
  • 2020-06-18
  • 1970-01-01
  • 2012-02-19
  • 2019-04-17
  • 2023-03-15
  • 2017-08-10
  • 2020-03-12
  • 1970-01-01
相关资源
最近更新 更多