在 Decodable 结构中以不同方式解码单个 var

Decoding a single var differently in a Decodable struct

我试图通过在 Codable struct 中创建自定义 init() 来将作为十六进制字符串发送的单个 var 解码为 UInt32,但是希望自动解码剩余的 vars。

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)
}