使用 Codable swift 解析时忽略数组中的空对象
ignore null object in array when parse with Codable swift
我正在用 swift Codable
解析这个 API
"total": 7,
"searchResult": [
null,
{
"name": "joe"
"family": "adam"
},
null,
{
"name": "martin"
"family": "lavrix"
},
{
"name": "sarah"
"family": "mia"
},
null,
{
"name": "ali"
"family": "abraham"
}
]
用这个 PaginationModel
:
class PaginationModel<T: Codable>: Codable {
var total: Int?
var data: T?
enum CodingKeys: String, CodingKey {
case total
case data = "searchResult"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.total = try container.decodeIfPresent(Int.self, forKey: .total)
self.data = try container.decodeIfPresent(T.self, forKey: .data)
}
}
和User
型号:
struct User: Codable {
var name: String?
var family: String?
}
我这样调用 jsonDecoder
来解析 API json:
let responseObject = try JSONDecoder().decode(PaginationModel<[User?]>.self, from: json)
现在我的问题是 null
在 searchResult
数组中。它解析正确,当我访问 paginationModel
中的 data
时,我在数组中找到了 null
。
如何在解析API时忽略所有null
,结果将是一个没有任何null
的数组
简单的解决方案,解码后过滤data
let responseObject = try JSONDecoder().decode(PaginationModel<[User?]>.self, from: data)
responseObject.data = responseObject.data?.filter{[=10=] != nil}
您可以在解码中添加数组类型检查:
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.total = try container.decodeIfPresent(Int.self, forKey: .total)
self.data = try container.decodeIfPresent(T.self, forKey: .data)
//add the following:
if let array = self.data as? Array<Any?> {
self.data = ( array.compactMap{[=10=]} as? T)
}
}
首先,我建议始终考虑 PaginationModel
由数组组成。您不必将 [User]
作为通用类型传递,您可以只传递 User
。然后解析器可以使用它解析数组的知识并自动处理 null
:
class PaginationModel<T: Codable>: Codable {
var total: Int?
var data: [T]?
enum CodingKeys: String, CodingKey {
case total
case data = "searchResult"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.total = try container.decodeIfPresent(Int.self, forKey: .total)
self.data = (try container.decodeIfPresent([T?].self, forKey: .data))?.compactMap { [=10=] }
}
}
您可能想在此处删除可选值并改用一些默认值:
class PaginationModel<T: Codable>: Codable {
var total: Int = 0
var data: [T] = []
enum CodingKeys: String, CodingKey {
case total
case data = "searchResult"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.total = (try container.decodeIfPresent(Int.self, forKey: .total)) ?? 0
self.data = ((try container.decodeIfPresent([T?].self, forKey: .data)) ?? []).compactMap { [=11=] }
}
}
请注意,您可以将可能 null/nil 的可解码变量定义为 [Float?](或任何类型),并使用可选的 '?'在数组括号内。
我正在用 swift Codable
解析这个 API"total": 7,
"searchResult": [
null,
{
"name": "joe"
"family": "adam"
},
null,
{
"name": "martin"
"family": "lavrix"
},
{
"name": "sarah"
"family": "mia"
},
null,
{
"name": "ali"
"family": "abraham"
}
]
用这个 PaginationModel
:
class PaginationModel<T: Codable>: Codable {
var total: Int?
var data: T?
enum CodingKeys: String, CodingKey {
case total
case data = "searchResult"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.total = try container.decodeIfPresent(Int.self, forKey: .total)
self.data = try container.decodeIfPresent(T.self, forKey: .data)
}
}
和User
型号:
struct User: Codable {
var name: String?
var family: String?
}
我这样调用 jsonDecoder
来解析 API json:
let responseObject = try JSONDecoder().decode(PaginationModel<[User?]>.self, from: json)
现在我的问题是 null
在 searchResult
数组中。它解析正确,当我访问 paginationModel
中的 data
时,我在数组中找到了 null
。
如何在解析API时忽略所有null
,结果将是一个没有任何null
简单的解决方案,解码后过滤data
let responseObject = try JSONDecoder().decode(PaginationModel<[User?]>.self, from: data)
responseObject.data = responseObject.data?.filter{[=10=] != nil}
您可以在解码中添加数组类型检查:
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.total = try container.decodeIfPresent(Int.self, forKey: .total)
self.data = try container.decodeIfPresent(T.self, forKey: .data)
//add the following:
if let array = self.data as? Array<Any?> {
self.data = ( array.compactMap{[=10=]} as? T)
}
}
首先,我建议始终考虑 PaginationModel
由数组组成。您不必将 [User]
作为通用类型传递,您可以只传递 User
。然后解析器可以使用它解析数组的知识并自动处理 null
:
class PaginationModel<T: Codable>: Codable {
var total: Int?
var data: [T]?
enum CodingKeys: String, CodingKey {
case total
case data = "searchResult"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.total = try container.decodeIfPresent(Int.self, forKey: .total)
self.data = (try container.decodeIfPresent([T?].self, forKey: .data))?.compactMap { [=10=] }
}
}
您可能想在此处删除可选值并改用一些默认值:
class PaginationModel<T: Codable>: Codable {
var total: Int = 0
var data: [T] = []
enum CodingKeys: String, CodingKey {
case total
case data = "searchResult"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.total = (try container.decodeIfPresent(Int.self, forKey: .total)) ?? 0
self.data = ((try container.decodeIfPresent([T?].self, forKey: .data)) ?? []).compactMap { [=11=] }
}
}
请注意,您可以将可能 null/nil 的可解码变量定义为 [Float?](或任何类型),并使用可选的 '?'在数组括号内。