Let\'s say we have a JSON structure like the following (commonly used in Firebase\'s Realtime Database):
{
\"18348b9b-9a49-4e04-ac35-37e38a8db1e2\": {
A couple things before I answer your question:
1: The comment (// id) makes the JSON invalid. JSON does not allow comments.
2: Where does the id property in BoringEntity come from?
struct BoringEntity: Decodable {
let id: String // where is it stored in the JSON???
let isActive: Bool
let age: Int
let company: String
}
If I overlook these things, you can wrap the array of BoringEntity in a struct (BoringEntities). Using [BoringEntity] directly is not advisable since you have to overshadow the default init(from decoder:) of Array.
The trick here is to make JSONDecoder gives you back the list of keys via the container.allKeys property:
struct BoringEntity: Decodable {
let isActive: Bool
let age: Int
let company: String
}
struct BoringEntities: Decodable {
var entities = [BoringEntity]()
// This really is just a stand-in to make the compiler happy.
// It doesn't actually do anything.
private struct PhantomKeys: CodingKey {
var intValue: Int?
var stringValue: String
init?(intValue: Int) { self.intValue = intValue; self.stringValue = "\(intValue)" }
init?(stringValue: String) { self.stringValue = stringValue }
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: PhantomKeys.self)
for key in container.allKeys {
let entity = try container.decode(BoringEntity.self, forKey: key)
entities.append(entity)
}
}
}
Usage:
let jsonData = """
{
"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"
}
}
""".data(using: .utf8)!
let entities = try JSONDecoder().decode(BoringEntities.self, from: jsonData).entities