我有一个基于嵌套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)
}
我能够获取根类和列表的值,但我在员工用户部分下获得了nil值。
答案 0 :(得分:0)
您的代码存在一些问题:
您的所有密钥都是可选的。供应商API将告诉您始终存在哪些键以及哪些键是可选的。关注那个。
decodeIfPresent
将无声地失败。在调试你的应用程序时,你想让事情失败,所以你可以在投入生产之前修复错误。
您编写的代码多于所需的代码。不需要所有init(from decoder: )
个函数。一个确实引起了你的问题。
您的问题是由此行引起的:
struct List : Codable {
init(from decoder: Decoder) throws {
...
employeeUser = try EmployeeUser(from: decoder)
}
}
您要求Swift将相同的JSON解码为List
和EmployeeUser
对象。显然,这是无效的。但是当你在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: )
。编译器会为你合成它们。
最后,修复这些选项!