Is it possible to decode single level JSON into 2 separate models?

感情迁移 提交于 2020-02-04 01:06:09

问题


I have a JSON response that contains information about a user.

{
  "userId": "123456789",
  "email": "\"some.email@some.domain.tld",
  "firstName": "\"foo\"",
  "lastName": "\"bar\"",
  "name": "\"foo bar",
  "bio": "\"boo baz\"",
  "age": "42"
}

I'd like to create 2 models, User and Profile from the same JSON, with a single request.

I'd then like Profile to be a property on the User struct.

At the moment, my standard struct looks like this -

struct User: Codable, Equatable {
    var userId: String
    var email: String
    var firstName: String
    var lastName: String
    var name: String?
    var bio: String?
    var age: Int?
}

I would prefer however to do something like this -

struct User: Codable, Equatable {
    var userId: String
    var email: String
    var profile: UserProfile // I'd like to wrap the profile info up in this field
}

struct UserProfile: Codable, Equatable {
    var firstName: String
    var lastName: String
    var name: String?
    var bio: String?
    var age: Int?
}

As profile does not exist on the response, I do not understand how I can decode the rest of the response into it.


回答1:


Firstly, you should consider making all of the fields on your model immutable.

It is good practice not to change your data, but create an updated copy.

However, this should work -

let json = Data("""
 {
   "userId": "123456789",
   "email": "some.email@some.domain.tld",
   "firstName": "foo",
   "lastName": "bar",
   "name": "foo bar",
   "bio": "boo baz",
   "age": 42
 }
""".utf8)

struct User: Codable, Equatable {
    let userId: String
    let email: String
    let profile: UserProfile

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        userId = try values.decode(String.self, forKey: .userId)
        email = try values.decode(String.self, forKey: .email)
        profile = try UserProfile(from: decoder)
    }

}

struct UserProfile: Codable, Equatable {
        let firstName: String
        let lastName: String
        let name: String?
        let bio: String?
        let age: Int?
}

var result = try! JSONDecoder().decode(User.self, from: json)
print(result.profile)


来源:https://stackoverflow.com/questions/59005602/is-it-possible-to-decode-single-level-json-into-2-separate-models

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!