Swift Codable 没有按预期工作?

Swift Codable not working as expected?

{
"responseBody": {
    "table": {
        "data": [
            [
                "Forth Record",
                null,
                0,
                "2018-08-23T18:30:01.000+0000",
                0,
                0,
                "HCL",
                "b74d10ef4fe246948cd036071787ff25"
            ],
            [
                "Third Record",
                "Testing custom object record 3",
                348,
                "2018-08-22T18:30:01.000+0000",
                36.45,
                4545.45,
                "HCL",
                "139fdba94bb143849fef220f105d66d0"
            ],
            [
                "Second Record",
                "Testing custom object record 2",
                56,
                "2018-08-22T18:30:01.000+0000",
                6577.67,
                567.67,
                "HAL",
                "606a06c93ea2473fb832e5daafa02df9"
            ],
            [
                "First Record",
                "Testing custom object record",
                75,
                "2018-08-22T18:30:01.000+0000",
                47.54,
                67.63,
                "HBL",
                "29c4125f3fa947b9b252318305e986c7"
            ]
        ]
    }
}
}

我想使用 swift 4 Codable 解析以上 JSON。请在下面查看我的对象层次结构

//ViewRecordResponse.swift
import Foundation
struct ViewRecordResponse : Codable {
    let responseBody : ViewRecord?

    enum CodingKeys: String, CodingKey {
        case responseBody = "responseBody"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        responseBody = try values.decodeIfPresent(ViewRecord.self, forKey: .responseBody)
    }
}

//ViewRecord.swift
import Foundation
struct ViewRecord : Codable {
    let table : Table?

    enum CodingKeys: String, CodingKey {
        case table = "table"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        table = try values.decodeIfPresent(Table.self, forKey: .table)
    }
}

//Table.swift
import Foundation
struct Table : Codable {
    let data : [[String?]]?

    enum CodingKeys: String, CodingKey {
        case data = "data"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        data = try values.decodeIfPresent([[String?]].self, forKey: .data)
    }
}

但是当我尝试使用 Codeable Mapping 解码 JSON 时,我收到一条错误消息

The data couldn't be read because it is missing.

The data couldn’t be read because it isn’t in the correct format.

解码为JSON对象的代码

do {
    let jsonDecoder = JSONDecoder()
    let response = try jsonDecoder.decode(ViewRecordResponse.self, from: data)
} catch let error {
    print(error.localizedDescription)
}

编辑 1 - 我的数据值

Printing description of data:
▿ 557 bytes
  - count : 557
▿ pointer : 0x0000000104a23005
  - pointerValue : 4372705285

编辑 2 - 数据对象不遵循任何特定模式问题

"data": [
            [
                456,
                31.04,
                10000,
                "Dummy Data",
                "text area dummy",
                "2018-08-27T18:30:01.000+0000",
                "UE",
                "4e67d5c02b0147b1bcfc00f459c0c612"
            ],

主要问题是data里面的嵌套数组是不是[[String?]],还有IntDouble 值。这很可能是错误的原因。

我的建议是使用(相当低估的)unkeyedContainer 将内部数组解码为结构。 decodeIfPresent 处理 null 值。

你的结构可以简单化,编码键和初始化器可以省略

struct ViewRecordResponse : Codable {
    let responseBody : ViewRecord
}

struct ViewRecord : Codable {
    let table : Table
}

struct Table : Codable {
    let data : [Record]
}

struct Record : Codable {
    let name : String
    let description : String?
    let index : Int
    let date : String
    let double1 : Double
    let double2 : Double
    let abbrev : String
    let sha : String

    init(from decoder: Decoder) throws {
        var arrayContrainer = try decoder.unkeyedContainer()
        name = try arrayContrainer.decode(String.self)
        description = try arrayContrainer.decodeIfPresent(String.self)
        index = try arrayContrainer.decode(Int.self)
        date = try arrayContrainer.decode(String.self)
        double1 = try arrayContrainer.decode(Double.self)
        double2 = try arrayContrainer.decode(Double.self)
        abbrev = try arrayContrainer.decode(String.self)
        sha = try arrayContrainer.decode(String.self)
    }
}

我不鼓励将每个结构放在一个单独的文件中,因为它们属于一起。