Be default, Decodable
protocol makes translation of JSON values to object values with no change. But sometimes you need to transform value during json decoding, for example, in JSON you get {id = "id10"}
but in your class instance you need to put number 10
into property id
(or into even property with different name).
You can implement method init(from:)
where you can do what you want with any of the values, for example:
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
latitude = try container.decode(Double.self, forKey:.latitude)
longitude = try container.decode(Double.self, forKey: .longitude)
// and for example there i can transform string "id10" to number 10
// and put it into desired field
}
Thats sounds great for me, but what if i want to change value just for one of the JSON fields and left all my other 20 fields with no change? In case of init(from:)
i should manually get and put values for every of 20 fields of my class! After years of objC coding it's intuitive for me to first call super's implementation of init(from:)
and then make changes just to some fields, but how i can achieve such effect with Swift and Decodable
protocol?
Currently you are forced to fully implement the encode
and decode
methods if you want to change the parsing of even a single property.
Some future version of Swift Codable will likely allow case-by-case handling of each property's encoding and decoding. But that Swift feature work is non-trivial and hasn't been prioritized yet:
Regardless, the goal is to likely offer a strongly-typed solution that allows you to do this on a case-by-case basis with out falling off the "cliff" into having to implement all of
encode(to:
andinit(from:
for the benefit of one property; the solution is likely nontrivial and would require a lot of API discussion to figure out how to do well, hence why we haven't been able to do this yet.- Itai Ferber, lead developer on Swift 4 Codable
https://bugs.swift.org/browse/SR-5249?focusedCommentId=32638