I am trying to decode a single var that is sent as a hexadecimal string into a UInt32 by creating a custom init() in a Codable struct, but would like the remaining vars to be decoded automatically.
struct MyStruct : Decodable {
var bits : UInt32
var other1 : Double
... // there are 20 more keys
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let string = try? container.decode(String.self, forKey: .bits) {
self.bits = convertToUInt32(string)
}
// Is there a way to decode remaining keys automatically?
???
}
}
The JSON I get is:
{
"bits" : "1a2b3fdd",
"other" : 12.34,
...
}
CodePudding user response:
You can create a property wrapper and provide a custom decoder for it. Then you can mark the properties that you want to be decoded:
@propertyWrapper
struct UInt32Hexa {
var wrappedValue: UInt32
}
extension UInt32Hexa: Decodable {
public init(from decoder: Decoder) throws {
let string = try decoder.singleValueContainer()
.decode(String.self)
guard let value = UInt32(string, radix: 16) else {
throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Corrupted data: \(string)"))
}
self.wrappedValue = value
}
}
Playground testing:
let json = """
{
"bits" : "1a2b3fdd",
"other" : 12.34
}
"""
struct MyStruct : Decodable {
@UInt32Hexa var bits: UInt32
let other: Double
}
do {
let test = try JSONDecoder().decode(MyStruct.self, from: Data(json.utf8))
print(test.bits) // 439042013
} catch {
print(error)
}
