给定一个嵌套对象结构的JSON对象,是这样的。
{
"users":[
{
"user":{
"name":"Adam",
"age":25
},
"address":{
"city":"Stockholm",
"country":"Sweden"
}
},
{
"user":{
"name":"Lilly",
"age":24
},
"address":{
"city":"Copenhagen",
"country":"Denmark"
}
}
]
}
如何才能实现正确的 Decodable
对象的实现,它看起来像这样。
struct User {
struct Address {
let city: String
let country: String
}
let name: String
let age: Int
let address: Address
}
请注意,Swift结构包含了一个嵌套结构 Address
而JSON对象有 address
在一个单独的对象中。是否有可能创建 Decodable
的实现来处理这种情况?
我试过各种方法,但所有这些方法都包括创建中间对象,这些对象后来会映射到 User
结构。是否可以创建一个不需要创建这些中间对象的实现?
你可以使用一个自定义的解码器,这样你就不用创建其他对象了。
struct User: Decodable {
let name: String
let age: Int
let address: Address
struct Address: Decodable {
let city: String
let country: String
}
enum CodingKeys: String, CodingKey {
case user
case address
}
enum UserKeys: String, CodingKey {
case name
case age
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let user = try container.nestedContainer(keyedBy: UserKeys.self, forKey: .user)
name = try user.decode(String.self, forKey: .name)
age = try user.decode(Int.self, forKey: .age)
address = try container.decode(Address.self, forKey: .address)
}
}
所以把你的数据放到一个游乐场中
let data = """
{
"users":[
{
"user":{
"name":"Adam",
"age":25
},
"address":{
"city":"Stockholm",
"country":"Sweden"
}
},
{
"user":{
"name":"Lilly",
"age":24
},
"address":{
"city":"Copenhagen",
"country":"Denmark"
}
}
]
}
""".data(using: .utf8)!
你可以像这样解码。
let decoder = JSONDecoder()
let result = try! decoder.decode([String:[User]].self, from: data)
或者你可以创建一个Users结构,这样你就不需要处理字典了。
struct Users: Decodable {
let users: [User]
}
let decoder = JSONDecoder()
let result = try! decoder.decode(Users.self, from: data)
你的意思是要压平 struct
使用这样的计算属性。
struct User: Codable {
struct UserDetail: Codable {
let name: String
let age: Int
}
struct Address: Codable {
let city: String
let country: String
}
let user: UserDetail
let address: Address
var name: String { user.name}
var age: Int { user.age }
var city: String { address.city }
var country: String { address.country }
}
print(user.name, user.age, user.city, user.country) // all the properties accessible within User struct