忽略Codable对象中的非Codable可选属性

KIO*_*KIO 11 json swift swift4 codable decodable

当符合Codable协议时,我不能轻易跳过非Codable类的可选属性

Ride结构,我们要跳过的编码解码driver财产,只要把它nil解码时:

  struct Ride: Codable {

    public var number: String
    public var passenger: Passenger? // Codable conforming
    public var driver: Driver?       // NSObject subclass, doesn't conform to Codable

    enum CodingKeys: String, CodingKey {
      case number
      case passenger
    }
  }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我得到一个编译错误

类型'驱动程序'不符合协议'可解码'

到目前为止,我提供的唯一解决方案是通过提供以下方法手动编码和解码:

public init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    number = try? values.decode(String.self, forKey: .number)
    passenger = try? values.decode(Passenger.self, forKey: .passenger)
}

public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(number, forKey: .number)
    try container.encode(passenger, forKey: .passenger)
}
Run Code Online (Sandbox Code Playgroud)

是否有另一种跳过可选属性的方法?对于更大的模型,这将更容易.

Pau*_*tos 23

尝试提供了一个默认值driver.例如,这在Xcode 9.0上编译时没有错误:

struct Ride: Codable {
    public var number: String
    public var passenger: Passenger? 
    public var driver: Driver? = nil

    private enum CodingKeys: String, CodingKey {
        case number
        case passenger
    }
}

struct Passenger: Codable { /* ... */ }

class Driver: NSObject { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

快速测试:

let rideJSON =
"""
{
    "number": "123"
}
""".data(using: .utf8)!

let ride = try! JSONDecoder().decode(Ride.self, from: rideJSON)
print(ride) /* Ride(number: "123", passenger: nil, driver: nil) */
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我用了一个,private CodingKeys因为这也是编译器默认做的事情;)

  • 打印的编译器错误对这个问题非常有帮助:`注意:无法自动合成 'Decodable',因为 'driver' 没有匹配的 CodingKey 并且没有默认值` (2认同)