解码JSON时出错-keyNotFound(CodingKeys

时间:2019-05-07 15:37:58

标签: json swift decoding

当我尝试解码此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>*/ ]

带有此Codable:

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 :(得分:0)

按照以下格式设置模型。还要根据您的回复检查数据类型。

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

答案 1 :(得分:0)

您显然出现了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设置为Date,然后再提供JSONDecoderdateDecodingStrategy (请参见下面的示例)。

例如:

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