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?]]
,还有Int
和Double
值。这很可能是错误的原因。
我的建议是使用(相当低估的)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)
}
}
我不鼓励将每个结构放在一个单独的文件中,因为它们属于一起。
{
"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?]]
,还有Int
和Double
值。这很可能是错误的原因。
我的建议是使用(相当低估的)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)
}
}
我不鼓励将每个结构放在一个单独的文件中,因为它们属于一起。