Let's say we have a JSON structure like the following (commonly used in Firebase's Realtime Database):
{
"18348b9b-9a49-4e04-ac35-37e38a8db1e2": {
"isActive": false,
"age": 29,
"company": "BALOOBA"
},
"20aca96e-663a-493c-8e9b-cb7b8272f817": {
"isActive": false,
"age": 39,
"company": "QUONATA"
},
"bd0c389b-2736-481a-9cf0-170600d36b6d": {
"isActive": false,
"age": 35,
"company": "EARTHMARK"
}
}
Expected solution:
Using Decodable
I'd like to convert it into an array of 3 elements:
struct BoringEntity: Decodable {
let id: String
let isActive: Bool
let age: Int
let company: String
init(from decoder: Decoder) throws {
// ...
}
}
let entities: [BoringEntity] = try! JSONDecoder()...
The id attribute corresponds to the json object's root string , e.g: 18348b9b-9a49-4e04-ac35-37e38a8db1e2
.
Workaround:
I have already tried several approaches but couldn't get the id attribute without requiring an auxiliary entity (or using optionals):
/// Incomplete BoringEntity version to make Decodable conformance possible.
struct BoringEntityIncomplete: Decodable {
let isActive: Bool
let age: Int
let company: String
}
// Decode to aux struct
let decoded = try! JSONDecoder().decode([String : BoringEntityIncomplete].self, for: jsonData)
// Map aux entities to BoringEntity
let entities = decoded.map { BoringEntity(...) }
Using init(from: Decoder)
isn't as trivial as in other cases since keyedContainer(,)
can't be used due to the fact that the key is unknown.
Is Decodable
unsuited for these types of cases ?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…