在 Decodable 结构中以不同方式解码单个 var
Decoding a single var differently in a Decodable struct
我试图通过在 Codable
struct
中创建自定义 init()
来将作为十六进制字符串发送的单个 var 解码为 UInt32
,但是希望自动解码剩余的 var
s。
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?
???
}
}
我得到的JSON
是:
{
"bits" : "1a2b3fdd",
"other" : 12.34,
...
}
您可以创建一个 属性 包装器并为其提供自定义解码器。然后你可以标记你想要解码的属性:
@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
}
}
游乐场测试:
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)
}
我试图通过在 Codable
struct
中创建自定义 init()
来将作为十六进制字符串发送的单个 var 解码为 UInt32
,但是希望自动解码剩余的 var
s。
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?
???
}
}
我得到的JSON
是:
{
"bits" : "1a2b3fdd",
"other" : 12.34,
...
}
您可以创建一个 属性 包装器并为其提供自定义解码器。然后你可以标记你想要解码的属性:
@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
}
}
游乐场测试:
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)
}