将JSON文件中的对象扁平化为Swift中的嵌套对象结构[重复]。

问题描述 投票:0回答:1

给定一个嵌套对象结构的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 结构。是否可以创建一个不需要创建这些中间对象的实现?

swift codable
1个回答
2
投票

你可以使用一个自定义的解码器,这样你就不用创建其他对象了。

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)

0
投票

你的意思是要压平 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
© www.soinside.com 2019 - 2024. All rights reserved.