I have many models that, depending on the endpoint, or serialized differently. My first attempt had a init(from decoder: Decoder)
riddled with nested try catch
blocks. I thought a better solution would be to extend JSONDecoder
so that when I initialize one, I can specify which endpoint i am pulling from. Then in my models init(from decoder: Decoder)
I could have a switch
like
switch
case endpoint1:
x = decoder.decode(Int.self, .x)
case endpoint2:
j = decoder.decode(String.self, .j)
The problem I ran into is that the class you have inside the init
is a Decoder
not a JSONDecoder
. I can't figure out a place that, if I extend Decoder
and allow myself to specify an endpoint, I could actually specify an endpoint, since JSONDecoder.decode()
instantiates it's own Decoder
behind the scenes. Thoughts?
I assumed after having previously used a CocoaPod for JSON Decoding and Encoding that I would actually need a way to handle different serializations of the same model, but thankfully Codable
handles this almost on its own. Any members that will not appear in every serialization, just mark as optional with ?
and if the Decoder can't find a key for it, it will skip it instead of fail. Similarly, the encoder will just encode members that are not nil
.
Example:
class Book: Codable {
var title: String
var numPages: Int?
var author: String?
enum CodingKeys: String, CodingKey {
case title
case numPages = "number_of_pages"
case author
}
}
This model will be successfully decoded from JSON Data that has:
However, because title is not optional, if the JSON Data doesn't contain a title, it will fail.