Ошибка декодирования - keyNotFound при разборе данных JSON - PullRequest
0 голосов
/ 16 октября 2019

Я использую API NASA в своем приложении для iOS для получения некоторых изображений. Мой ответ от сервера выглядит следующим образом:

{
  "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"
}

URL моего запроса:

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 голосов
/ 16 октября 2019

Это ... выглядит хорошо? (Предполагая, что Resource также Decodable, но это будет отдельной проблемой). Возможно, ошибка на самом деле говорит вам правду, возможно, вы пытаетесь декодировать BLOB-объект JSON, который не имеет значения даты.

Вы можете явно увидеть то, что мы пытаемся декодировать, с добавленной печатью непосредственно перед тем, как мы попытаемся декодировать:

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

Затем отдельно, если поле даты не гарантированно существует впри каждом ответе вы должны сделать его необязательным:

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)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...