You could do it in two steps if you want to. First declare a struct for the received json
struct KeyValue: Decodable {
let key: String
let value: String
}
Then decode the json and map the result into a dictionary using the key/value pairs.
do {
let result = try JSONDecoder().decode([String: [KeyValue]].self, from: data)
if let array = result["user"] {
let dict = array.reduce(into: [:]) { $0[$1.key] = $1.value}
Then encode this dictionary into json and back again using a struct for User
struct User: Decodable {
let id: String
let name: String
let group: String
let city: String
let country: String
}
let userData = try JSONEncoder().encode(dict)
let user = try JSONDecoder().decode(User.self, from: userData)
The whole code block then becomes
do {
let decoder = JSONDecoder()
let result = try decoder.decode([String: [KeyValue]].self, from: data)
if let array = result["user"] {
let dict = array.reduce(into: [:]) { $0[$1.key] = $1.value}
let userData = try JSONEncoder().encode(dict)
let user = try decoder.decode(User.self, from: userData)
//...
}
} catch {
print(error)
}
A bit cumbersome but no manual key/property matching is needed.
Codableprotocol in this case. This is an extremely weird way organize API data. You'd need to parse this out manually from data object.Datainto theDictionaryand parsing stuff manually by each key. Although if the list of properties could change and miss some of the fields, you'd have a hard time combining stuff into one solid User object anyway.