将 JSON 文件中的对象扁平化为 Swift 中的嵌套对象结构
Flattened objects in JSON file to nested object structure in Swift
给定一个 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
:
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
您可以使用自定义解码器,这样就不必创建其他对象。
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)
给定一个 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
:
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
您可以使用自定义解码器,这样就不必创建其他对象。
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)