用于嵌套 JSON 解析的模型类的 Swift4 编码解码



我有一个基于嵌套 json 响应创建的 swift 模型类,如下所示

struct RootClass : Codable {
let details : String?
let itemCount : Int?
let list : [List]?
enum CodingKeys: String, CodingKey {
case details = "Details"
case itemCount = "ItemCount"
case list = "List"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
details = try values.decodeIfPresent(String.self, forKey: .details)
itemCount = try values.decodeIfPresent(Int.self, forKey: .itemCount)
list = try values.decodeIfPresent([List].self, forKey: .list)
}
}
struct List : Codable {
let companyID : Int?
let employeeCount : Int?
let employeeUser : EmployeeUser?
enum CodingKeys: String, CodingKey {
case companyID = "CompanyID"
case employeeCount = "EmployeeCount"
case employeeUser = "EmployeeUser"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
companyID = try values.decodeIfPresent(Int.self, forKey: .companyID)
employeeCount = try values.decodeIfPresent(Int.self, forKey: .employeeCount)
employeeUser = try EmployeeUser(from: decoder)
}
}
struct EmployeeUser : Codable {
let mobileNumber : String?
let name : String?
enum CodingKeys: String, CodingKey {
case mobileNumber = "MobileNumber"
case name = "Name"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
mobileNumber = try values.decodeIfPresent(String.self, forKey: .mobileNumber)
name = try values.decodeIfPresent(String.self, forKey: .name)
}
}

我的 JSON 响应是

{
"Details": null,
"List": [
{
"CompanyID": 140,
"EmployeeUser": {
"Name": " raghu2",
"MobileNumber": "8718718710"
},
"EmployeeCount": 0
},
{
"CompanyID": 140,
"EmployeeUser": {
"Name": "new emp reg",
"MobileNumber": "1"
},
"EmployeeCount": 0
}
],
"ItemCount": 0
}

我正在尝试像解析它一样

guard let data = data else { return }
do {
let decoder = JSONDecoder()
let gitData = try decoder.decode(RootClass.self, from: data)
print(gitData.itemCount ?? "")
print(gitData.list![0].employeeUser?.mobileNumber ?? "")
}
catch let err {
print("Err", err)
}

我能够获取根类和列表的值,但我在员工用户部分下获得零值。

你的代码有几个问题:

  • 您的所有密钥都是可选的。供应商 API 将告诉您哪些密钥始终存在,哪些密钥是可选的。遵循它。

  • 如果decodeIfPresent无法解码密钥,它将静默失败。在调试应用时,你希望事情一声失败,以便在投入生产之前修复错误。

  • 您编写的代码比需要的要多得多。不需要所有这些init(from decoder: )函数。一个确实导致了你的问题。

您的问题是由以下行引起的:

struct List : Codable {
init(from decoder: Decoder) throws {
...
employeeUser = try EmployeeUser(from: decoder)
}
}

您要求 Swift 将相同的 JSON 解码为ListEmployeeUser对象。显然,这是无效的。但是当你在 RootClass 中解码list时,你调用decodeIfPresent

// In Rootclass
list = try values.decodeIfPresent([List].self, forKey: .list)

这个电话默默地失败了,你永远不知道问题是什么!


溶液

将初始化employeeUser的方式更改为以下内容:

employeeUser = try values.decodeIfPresent(EmployeeUser.self, forKey: .employeeUser)

但最优雅的解决方案是 删除所有这些init(from decoder: ).编译器将为您合成它们。

最后,修复这些可选内容!

最新更新