Swift Codable无法正常工作?

时间:2018-08-24 11:24:43

标签: 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"
            ]
        ]
    }
}
}

我想使用快速4 JSON来解析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)
    }
}

但是当我尝试使用Codeable Mapping解码JSON时,出现错误提示

  

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

     

由于数据格式不正确,因此无法读取。

用于解码为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"
            ],

1 个答案:

答案 0 :(得分:7)

主要问题是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)
    }
}

我不鼓励将每个结构归为一类放在单独的文件中。