将 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)