Swift Codable没有按预期工作?

Vis*_*l16 7 json swift swift4 decodable

{
"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"
            ]
        ]
    }
}
}
Run Code Online (Sandbox Code Playgroud)

我想JSON用swift 4 解析上面的内容Codable.请参阅下面的对象层次结构

//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)
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试使用可编程映射解码JSON时,我得到了一个错误说法

由于缺少数据,因此无法读取数据.

无法读取数据,因为格式不正确.

解码为JSON对象的代码

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

编辑1 - 我的数据值

Printing description of data:
? 557 bytes
  - count : 557
? pointer : 0x0000000104a23005
  - pointerValue : 4372705285
Run Code Online (Sandbox Code Playgroud)

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

"data": [
            [
                456,
                31.04,
                10000,
                "Dummy Data",
                "text area dummy",
                "2018-08-27T18:30:01.000+0000",
                "UE",
                "4e67d5c02b0147b1bcfc00f459c0c612"
            ],
Run Code Online (Sandbox Code Playgroud)

vad*_*ian 8

主要的问题是,在嵌套数组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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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