解码错误-解析JSON数据时出现keyNotFound

时间:2019-10-16 19:59:01

标签: json swift

我在我的iOS应用程序中使用NASA API来获取一些图像。我从服务器收到的响应如下:

{
  "date": "2014-02-04T03:30:01", 
  "id": "LC8_L1T_TOA/LC81270592014035LGN00", 
  "resource": {
    "dataset": "LC8_L1T_TOA", 
    "planet": "earth"
  }, 
  "service_version": "v1", 
  "url": "https://earthengine.googleapis.com/api/thumb?thumbid=bc77b079c8ecd07cd668c576c22b83a4&token=a16639b0d38dd68c586c24a6ee5299d9"
}

我的请求网址是:

https://api.nasa.gov/planetary/earth/imagery/?lon=100.75&lat=1.5&date=2014-02-01&api_key=DEMO_KEY

我解码此响应的结构是:

import Foundation

// MARK: - EarthImages
struct EarthImages: Codable {
    let date: String
    let id: String
    let resource: Resource
    let serviceVersion: String
    let url: String

    private enum CodingKeys: String, CodingKey {
        case date = "date"
        case id = "id"
        case resource = "resource"
        case serviceVersion = "service_version"
        case url = "url"
    }
}

问题是-当我尝试使用以下代码解码响应

        URLSession.shared.dataTask(with: url) { data, response, error in
        if let data = data {
            do {
                let earthImages = try JSONDecoder().decode(EarthImages.self, from: data)
                print(earthImages.url)
            }
            catch let error{
                print(error)
            }}

    }.resume()

我进入控制台。

keyNotFound(CodingKeys(stringValue: "date", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"date\", intValue: nil) (\"date\").", underlyingError: nil))

我使用PAW来检查是否得到正确的响应,并且它可以正常工作,因此问题很可能出在我的代码中。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

看起来...还好吗? (假设Resource也是Decodable,但这将是一个单独的问题)。也许错误实际上是在告诉您事实,您可能正在尝试解码没有日期值的JSON Blob。

在我们尝试解码之前,您可以显式地看到我们正在尝试通过添加印刷品来解码的内容:

if let data = data {
    print(String(data: data, encoding: .utf8)!)
    do {
    ...

然后分开,如果不能保证每个响应中都存在date字段,则应将其设为可选:

struct EarthImages: Codable {
    let date: String?
    let id: String
    let resource: Resource
    let serviceVersion: String
    let url: String
}

请注意,如果字符串枚举与枚举大小写完全相同,则无需重新声明:

enum CodingKeys: String, CodingKey {
    case date // "date" is implied
    case id
    case resource
    case serviceVersion = "service_version"
    case url
}

另一个有趣的事实:JSONDecoder也可以自动从蛇格转换而无需定义CodingKeys(如果每个键都一致)。

所以您也可以这样做:

struct EarthImages: Codable {
    let date: String
    let id: String
    let resource: Resource
    let serviceVersion: String
    let url: String
}

...

do {
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let earthImages = try decoder.decode(EarthImages.self, from: data)
}