It appears that the Character class in Swift 4 does not implement the Codable protocol. I would like to understand the rationale for this, as it seems that the class would qualify as a foundational class in Swift.
Looking at the (intentionally stripped bare) recursive class below, what would then be the best way to make it Codable while retaining the use of Character as the Dictionary key?
class MyClass: Codable { <- does not compile
var myProperty: [Character: MyClass]?
var myOtherProperty: Int = 42
}
Thank you!
You can make Character
conform to Codable
protocol as follow:
extension Character: Codable {
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
let string = try container.decode(String.self)
guard !string.isEmpty else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Decoder expected a Character but found an empty string.")
}
guard string.count == 1 else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Decoder expected a Character but found a string: \(string)")
}
self = string[string.startIndex]
}
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(String(self))
}
}
Playground testing
let aClass = AClass()
let bClass = AClass()
bClass.myOtherProperty = 10
aClass.myProperty = [:]
aClass.myProperty?["B"] = bClass
aClass.myOtherProperty = 20
do {
let jsonData = try JSONEncoder().encode(aClass)
print(String(data: jsonData, encoding: .utf8)!) // "{"myProperty":[["B"],{"myOtherProperty":10}],"myOtherProperty":20}\n"
let decodedObject = try JSONDecoder().decode(AClass.self, from: jsonData)
print(decodedObject.myProperty) // "Optional(["B": __lldb_expr_73.AClass])\n"
print(decodedObject.myOtherProperty) // 20
} catch {
print(error)
}