How do I customise the behaviour of JSONDecoder for primitive
types like Int, Bool?
Here is the problem:
Backend cannot be relied upon for types. Eg: Bool can come as true/false or "true"/"false"(bool can come wrapped in double quotes)
We have at least 300 Codable structs having average 15 properties in them and writing decoding logic is cumbersome. Also the logic remains more or less same hence the code has become repetitive
Hence I am looking for a solution such that if there is a Type mismatch
primitive types should be able to handle it and if not then it should be set to nil
provided that type is Optional.
I tried multiple approaches for this
1. Having Wrapper on all the primitive types and handling the decoding logic. Below is an example of wrapper on Bool
struct Bool1: Codable{
private var bool: Bool?
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let b = try? container.decode(Bool.self) {
self.bool = b
} else if let string = try? container.decode(String.self) {
if string.lowercased() == "true" {
self.bool = true
} else if string.lowercased() == "false" {
self.bool = false
} else {
throw Error()
}
}
}
}
but this created unnecessary confusion among fellow developers as Wrapped types do not come out as naturally as the Native ones. Also the value cannot be accessed directly (it always need xyz.bool) to extract the raw value
2. Create a new protocol inherited from Decodable and subclass JSONDecoder
protocol KKDecodable: Decodable {
init(decoder1: Decoder)
}
extension Bool: KKDecodable {
init(decoder1: Decoder) {
// Logic for creating Bool from different types
}
}
class JSONDecoder1: JSONDecoder {
func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : KKDecodable {
// Some code that would invoke `init(decoder1: Decoder)`
// which is defined in `KKDecodable`
}
}
I was not able to write working code using this method