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