Let's say I need to transform a date string I received from a web service to a Date object.
Using ObjectMapper, that was easy:
class Example: Mappable {
var date: Date?
required init?(map: Map) { }
func mapping(map: Map) {
date <- (map["date_of_interest"], GenericTransform().dateTransform)
}
}
I just had to implement a tranformer ("GenericTransform" in this case) for date, and pass it as an argument along with the key name to decode.
Now, using Codable:
class Example2: Codable {
var name: String
var age: Int
var date: Date?
enum CodingKeys: String, CodingKey {
case name, age
case date = "date_of_interest"
}
}
To transform a date, in my understanding, I'd have to either:
1) Pass a dateDecodingStrategy to my JSONDecoder, which I don't want to, because I'm trying to keep that part of the code as a generic function.
or
2) Implement an init(from decoder: Decoder)
inside Example2, which I also don't want to, because of the boilerplate code I'd have to write to decode all the other properties (which would be automatically generated otherwise):
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
age = try container.decode(Int.self, forKey: .age)
let dateString = try container.decode(String.self, forKey: .date)
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
if let date = formatter.date(from: dateString) {
self.date = date
} else {
//throw error
}
}
My question is: is there an easier way to do it than options 1 and 2 above? Maybe tweaking the CodingKeys enum somehow?
EDIT:
The problem is not only about dates, actually. In this project that I'm working on, there are many custom transformations being done using TransformOf<ObjectType, JSONType>
from ObjectMapper.
For example, a color transformation of a hex code received from a web service into a UIColor is done using this bit of code:
let colorTransform = TransformOf<UIColor, String>(fromJSON: { (value) -> UIColor? in
if let value = value {
return UIColor().hexStringToUIColor(hex: value)
}
return nil
}, toJSON: { _ in
return nil
})
I'm trying to remove ObjectMapper from the project, making these same transformations using Codable, so only using a custom dateDecodingStrategy will not suffice.
How would you guys do it? Implement a custom init(from decoder: Decoder)
for every class that has to decode, for example, a color hex code?