I have a problem decoding a JSON structure which I cannot change to make it easier to decode (it's coming from firebase)..
How do I decode the following JSON into objects? The problem is how to convert "7E7-M001". It's the name of a container which has drawers. The drawers name is also used as a key.
{
"7E7-M001" : {
"Drawer1" : {
"101" : {
"Partnumber" : "F101"
},
"102" : {
"Partnumber" : "F121"
}
}
},
"7E7-M002": {
"Drawer1": {
"201": {
"Partnumber": "F201"
},
"202": {
"Partnumber": "F221"
}
}
}
}
What do I have to fix in the Container & Drawer class to have the key as a title property and an array of objects in these classes ?
class Container: Codable {
var title: String
var drawers: [Drawer]
}
class Drawer: Codable {
var title: String
var tools: [Tool]
}
class Tool: Codable {
var title: String
var partNumber: String
enum CodingKeys: String, CodingKey {
case partNumber = "Partnumber"
}
}
In this case we can't create static
codable
classes for this JSON. Better useJSON serialization
and retrive it.First I'm going to make some slight simplifications so I can focus on the important points of this question. I'm going to make everything immutable, replace the classes with structs, and only implement Decodable. Making this Encodable is a separate issue.
The central tool for handling unknown value keys is a CodingKey that can handle any string:
The second important tool is the ability to know your own title. That means asking the decoder "where are we?" That's the last element in the current coding path.
And then we need a way to decode elements that are "titled" this way:
With that, we can invent a protocol for these "titled" things and decode them:
And that's most of the work. We can use this protocol to make decoding pretty easy for the upper-level layers. Just implement
init(title:elements:)
.Tool
is a little different since it's a leaf node and has other things to decode.That just leaves the very top level. We'll create a
Containers
type just to wrap things up.And to use it, decode the top level
Containers
:Note that since JSON objects are not order-preserving, the arrays may not be in the same order as the JSON, and may not be in the same order between runs.
Gist