Ошибка декодирования JSON - keyNotFound (CodingKeys - PullRequest
0 голосов
/ 07 мая 2019

Когда я пытаюсь декодировать этот JSON:

"polls": [
{
  "title": "title",
  "date": "date",
  "summary": "summary",
  "stats": {
    "total": {
      "dagegen gestimmt": 139,
      "nicht beteiligt": 114,
      "dafür gestimmt": 454,
      "enthalten": 2
    },
  }
}, /*<and about 76 of this>*/ ]

с этим кодируемым:

struct poll: Codable {
  var stats: stats
  var title: String?
  var date: String?
  var summary: String?

  struct stats: Codable {
      var total: total
      struct total: Codable {
          var nays: Int
          var yays: Int
          var nas: Int
          var abstentions: Int

          private enum CodingKeys: String, CodingKey {
             case yays = "dafür gestimmt"
             case nays = "dagegen gestimmt"
             case nas = "nicht beteiligt"
             case abstentions = "enthalten"
          }
      }
  }
}

Я получаю следующую ошибку keyNotFound(CodingKeys(stringValue: "dagegen gestimmt", intValue: nil) (если вам нужен полный текст ошибки, скажите мне)

Я пытался ответить на некоторые из похожих вопросов, но ничего не получалось.

Ответы [ 2 ]

0 голосов
/ 07 мая 2019

По-видимому, у вас есть случаи total, где dagegen gestimmt отсутствует.Итак, сделайте это Optional, например Int?:

struct Poll: Codable {
    let stats: Stats
    let title: String?
    let date: Date?
    let summary: String?

    struct Stats: Codable {
        let total: Total

        struct Total: Codable {
            let nays: Int?
            let yays: Int?
            let nas: Int?
            let abstentions: Int?

            private enum CodingKeys: String, CodingKey {
                case yays = "dafür gestimmt"
                case nays = "dagegen gestimmt"
                case nas = "nicht beteiligt"
                case abstentions = "enthalten"
            }
        }
    }
}

Я бы также предложил следующее, также отраженное в приведенном выше:

  • Имена начальных типов (например, ваши struct имена) с заглавной буквой;
  • Используйте let вместо var, так как мы всегда должны поддерживать неизменность, если вы действительно не собираетесь изменять эти значения в этом struct
  • Если ваша дата имеет согласованный формат, я бы предложил сделать тип date a Date, а затем вы можете указать JSONDecoder a dateDecodingStrategy, который соответствует (см. пример ниже).).

Например:

let data = """
    {
        "polls": [
            {
                "title": "New Years Poll",
                "date": "2019-01-01",
                "summary": "summary",
                "stats": {
                    "total": {
                        "dagegen gestimmt": 139,
                        "nicht beteiligt": 114,
                        "dafür gestimmt": 454,
                        "enthalten": 2
                    }
                }
            },{
                "title": "Caesar's Last Poll",
                "date": "2019-03-15",
                "summary": "summary2",
                "stats": {
                    "total": {
                        "dafür gestimmt": 42
                    }
                }
            }
        ]
    }
    """.data(using: .utf8)!

struct Response: Codable {
    let polls: [Poll]
}

do {
    let decoderDateFormatter = DateFormatter()
    decoderDateFormatter.dateFormat = "yyyy-MM-dd"
    decoderDateFormatter.locale = Locale(identifier: "en_US_POSIX")

    let userInterfaceDateFormatter = DateFormatter()
    userInterfaceDateFormatter.dateStyle = .long

    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .formatted(decoderDateFormatter)
    let response = try decoder.decode(Response.self, from: data)
    let polls = response.polls
    for poll in polls {
        print(poll.title ?? "No title")
        print("  date:", poll.date.map { userInterfaceDateFormatter.string(from: $0) } ?? "No date supplied")
        print("  yays:", poll.stats.total.yays ?? 0)
        print("  nays:", poll.stats.total.nays ?? 0)
    }
} catch {
    print(error)
}

Что производит:

New Years Poll
  date: January 1, 2019
  yays: 454
  nays: 139
Caesar's Last Poll
  date: March 15, 2019
  yays: 42
  nays: 0
0 голосов
/ 07 мая 2019

Установите модель в соответствии со следующим форматом. Также проверьте тип данных согласно вашему ответу.

struct PollsModel:Codable{
    var polls : [PollsArrayModel]

    enum CodingKeys:String, CodingKey{
        case polls
    }

    struct PollsArrayModel:Codable{
        var title : String?
        var date : String?
        var summary : String?
        var stats : PollsStatsModel

        enum CodingKeys:String, CodingKey{
            case title
            case date
            case summary
            case stats
        }

        struct PollsStatsModel:Codable{

            var total : PollsStatsTotalModel

            enum CodingKeys:String, CodingKey{
                case total
            }

            struct PollsStatsTotalModel:Codable{

                var dagegen_gestimmt : Int?
                var nicht_beteiligt : Int?
                var dafür_gestimmt : Int?
                var enthalten : Int?

                enum CodingKeys:String, CodingKey{
                    case dagegen_gestimmt = "dagegen gestimmt"
                    case nicht_beteiligt = "nicht beteiligt"
                    case dafür_gestimmt = "dafür gestimmt"
                    case enthalten = "enthalten"
                }
            }
        }
    }
}
...