【问题标题】:JSON response decoding to nil in swiftJSON响应迅速解码为零
【发布时间】:2021-10-21 02:06:31
【问题描述】:
struct Jresponse: Decodable{
            //var results: [Any]
            var resolution: Int?
            var elevation:  Int?
            var location: Int?
            var lat: Int?
            var lng: Int?
        }
        guard let url = URL(string: "https://maps.googleapis.com/maps/api/elevation/json?&locations=\(finalStringConvertedCoordinates)&key=\(apiKey)") else {
                    print("Error: cannot create URL")
                    return
                }
                // Create the url request
                var request = URLRequest(url: url)
                request.httpMethod = "GET"
                URLSession.shared.dataTask(with: request) { data, response, error in
                    guard error == nil else {
                        print("Error: error calling GET")
                        print(error!)
                        return
                    }
                    guard let data = data else {
                        print("Error: Did not receive data")
                        return
                    }
                    guard let response = response as? HTTPURLResponse, (200 ..< 299) ~= response.statusCode else {
                        print("Error: HTTP request failed")
                        return
                    }
                    do {
                        guard let jsonObject = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
                            print("Error: Cannot convert data to JSON object")
                            return
                        }
                        guard let prettyJsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: []) else {
                            print("Error: Cannot convert JSON object to Pretty JSON data")
                            return
                        }
                        guard let prettyPrintedJson = String(data: prettyJsonData, encoding: .utf8)
                        else {
                            print("Error: Could print JSON in String")
                            return
                        }
                        //print(prettyPrintedJson)
                        jsonResponse = prettyPrintedJson
                    } catch {
                        print("Error: Trying to convert JSON data to string")
                        return
                    }
                    let decoder = JSONDecoder()
                    let jrData = jsonResponse.data(using: .utf8)
                    let jsonResponseProcessed = try! decoder.decode(Jresponse.self, from: jrData! )
                    print(jsonResponseProcessed)
                }.resume()
        
            }

上面的代码包含响应的请求和解码,我对 JSON 不熟悉,这可能很明显。

我遇到的问题是打印时返回的结果都是 nil。

以前我没有使用解码,而是尝试将数据处理成一个数组,在其中可以检索单个值进行比较。

数组方法会产生无法管理的数据,因为元素没有按可管理的顺序分隔。

像这样[零响应][1]

包含 print("---> data: (String(data: data, encoding: .utf8))") 的输出看起来像这样。

[输出可见这里][2]

---> 数据:可选(“{\n“结果”:[\n {\n“海拔”:11.59268283843994,\n“位置”:{\n“纬度”:37.78533554077148,\n“lng " : -122.4059982299805\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 11.68190288543701,\n "位置" : {\n "纬度" : 37.78538513183594,\n "lng" : -122.4059143066406\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 11.86490249633789,\n "位置" : {\n "lat" : 37.78548812866211,\n "lng" -122.4059143066406\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 11.53255939483643,\n "位置" : {\n "纬度" : 37.78533554077148,\n "lng:" 122.4061584472656\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "高度" : 11.46291351318359,\n "位置" : {\n "纬度" : 37.78533554077148,\n "lng" : -122.4063262939453\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 11.69645023345947,\n位置”:{\n“纬度”:37.78558731079102,\n“lng”:-122.4059143066406\n},\n“分辨率”:0.5964969992637634\n},\n {\n“海拔”:11.79109859466553,\n“ " : {\n "纬度" : 37.78569030761719,\n "lng" : -122.4059143066406\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 11.35733222961426,\n"位置" : {\n "纬度" : 37.78533554077148,\n "lng" : -122.4064865112305\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 11.57364559173584,\n "位置" {\n "lat" : 37.78533554077148,\n "lng" : -122.4066467285156\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 11.7429027557373,\n "位置" : {\n "纬度" : 37.78578948974609,\n "lng" : -122.4059143066406\n ,\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 12.02133083343506,\n "位置" : {\n "纬度" : 37.78589248657227,\n "lng" : -122.4059143066406\n \n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 11.66207313537598,\n "位置" : {\n "纬度" : 37.78533554077148,\n "lng" : -122.40681\45751953\n } n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 11.85497093200684,\n "位置" : {\n "纬度" : 37.78536987304688,\n "lng" : -122.4069137573242\n }, "分辨率" : 0.5964969992637634\n },\n {\n "高度" : 12.220119476 31836,\n "位置" : {\n "纬度" : 37.78599548339844,\n "lng" : -122.4059143066406\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 12.5967053 ,\n "位置" : {\n "纬度" : 37.78609466552734,\n "lng" : -122.4059143066406\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 12.1927595138594 \n "位置" : {\n "纬度" : 37.78546905517578,\n "lng" : -122.4069137573242\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 12.13\9259872436, n "位置" : {\n "纬度" : 37.78557205200195,\n "lng" : -122.4069137573242\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 12.98763847351074,\n “位置”:{\n “纬度”:37.78619766235352,\n “lng”:-122.405914 3066406\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 13.3654317855835,\n "位置" : {\n "纬度" : 37.78629684448242,\n "lng" : -122.405914 \n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 12.14237785339355,\n "位置" : {\n "纬度" : 37.78567504882812,\n "lng" : -122.406913757324 n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 12.26948738098145,\n "位置" : {\n "纬度" : 37.78577423095703,\n "lng" : -122.4069137573242\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 13.74397277832031,\n "位置" : {\n "纬度" : 37.78633499145508,\n "lng" : -122.4060211181641\n ,\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 14.1032075881958,\n "位置" : {\n "lat" : 37.78633499145508,\n "lng" : -122.4061889648438\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" 12.31325626373291,\n "位置" : {\n "纬度" : 37.7858772277832,\n "lng" : -122.4069137573242\n },\n "分辨率" : 0.5964969992637634\n },\n {182428128121: ,\n "位置" : {\n "lat" : 37.78598022460938,\n "lng" : -122.4069137573242\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 14.129924850463 \n "位置" : {\n "纬度" : 37.78633499145508,\n "lng" : -122.4063491821289\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 14.4321174621582,\ n "位置" : {\n "纬度" : 37.78633499145508,\n "lng" : -122.4065093994141\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 12.53042221069336,\n "位置" : {\n "lat" : 37.78607940673828,\n "lng :" 122.4069137573242\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 13.14097881317139,\n "位置" : {\n "lat" : 37.786182403564245,\n -69137. \n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 14.39413261413574,\n "位置" : {\n "纬度" : 37.78633499145508,\n "lng" : -122.4066696166992 n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 14.40865802764893,\n "位置" : {\n "纬度" : 37.78633499145508,\n "lng" : -122.406837463378\n },\n "分辨率" : 0.5964969992637634\n },\n {\n "海拔" : 13.98401737213135,\n "位置" : {\n "纬度" : 37.78628158569336,\n "lng" : -122.4069137573242\n },\n "分辨率" : 0.5964969992637634\n }\n ],状态" : "确定"\n}\n") Jresponse(分辨率:无,海拔:无,位置:无,纬度:无,lng:无) [1]:https://i.stack.imgur.com/uaRZZ.png [2]:https://i.stack.imgur.com/MWJZX.png

【问题讨论】:

  • 我们需要您在 API 调用后获得的 JSON
  • 你能把这个打印:print("---&gt; data: \(String(data: data, encoding: .utf8))") 放在guard let data = data else {....} 之后,然后告诉我们打印的内容吗?
  • 应该是decoder.decode(Jresponse.self, from: data),注意变量data的使用
  • 感谢您的回复。 Joakim 我尝试使用数据没有任何变化。 Workingdog 我将编辑帖子并添加回复。我在“jsonresponseprocessed”中的值仍然为零
  • 请将完整的打印结果显示为文本,而不是图片的一半。

标签: json swift httprequest google-elevation-api


【解决方案1】:

解码失败

您无法获取任何数据的最可能原因是您的数据模型(此处定义为结构 Jresponse)不适合后端发回的实际 JSON 格式。

我已经快速检查了 google map api doc 的海拔,看起来您应该在顶层收到一个带有 ElevationResult 数组的 json 对象。然后每个结果将包含分辨率、高度和位置。

请参考https://developers.google.com/maps/documentation/elevation/overview#ElevationResult

正确的数据模型


struct ElevationResponse: Decodable {
    let results: [ElevationResult]
}

struct ElevationResult: Decodable {
     let elevation: Double
     let location: LatLngLiteral
     let resolution: Double?
}

struct LatLngLiteral: Decodable {
     let lat: Double
     let lng: Double
}

更改解码模型

let jsonResponseProcessed = try! decoder.decode(ElevationResponse.self, from: data)

旁白

  1. 解码数据的方式可以更加现代化和简洁
  2. 注意不要使用 force unwrap 和 force try
  3. 发布问题时,请注意代码缩进,首先在 Xcode 中选择您的代码并执行ctrl + i 以提高其可读性。然后才将其复制到您的 Stackoverflow 问题中。

【讨论】:

  • 谢谢。这帮助我解决了问题,也提高了我对处理响应的理解。
  • @DESWIJ 好的,但请注意,分辨率应该是可选的,否则您可能会遇到一些错误。 Google API 文档明确说明了这一点。
  • 我一定会将该结果保留为可选的。谢谢您的帮助。我没有足够的代表来支持你
  • 我如何查询生成的结构以获取特定的高程索引作为示例?我一直在尝试,我可以得到集合的第一个和最后一个元素,但没有别的。
  • @DESWIJ jsonResponseProcessed.results[1].elevation 将 1 替换为任何所需的索引
【解决方案2】:

按照@Joakim Danielson 的建议,您应该将代码修改为

 let jsonResponseProcessed = try! decoder.decode(Jresponse.self, from: data )

根据谷歌文档,在:https://developers.google.com/maps/documentation/elevation/start

你应该使用这个数据结构:EDIT

struct Jresponse: Codable {
    let results: [Result]
    let status: String?
}

struct Result: Codable {
    let elevation: Double
    let location: Location
    let resolution: Double?
}

struct Location: Codable {
    let lat, lng: Double
}

【讨论】:

  • 相同意见但分辨率是可选的,如果载荷中不存在解码将失败
  • 感谢您的帮助,我的问题已解决,我确实有一个问题。当我访问这些值时,我可以检索单个项目。例如:print(JsonResponseProcessed["elevation"])
  • @DESWIJ 如果要访问其中一个接收到的高程结果,可以执行以下操作:print(jsonResponseProcessed.results.first!.elevation) 也可以使用正则下标直接访问指定索引,但要注意索引超出范围。 (你也应该安全地展开,不要使用强制展开它只是为了示例)
  • 用“让状态:字符串?”更新了我的答案以防万一它不存在。和同样提到的分辨率。
  • 如果我想访问一个特定的项目,我该怎么做。我试图获得一个单独的海拔元素,我给出了错误“ElevationResponse”没有下标”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-04
  • 2017-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多