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

Posted

技术标签:

【中文标题】忽略 Codable 对象中的非 Codable 可选属性【英文标题】:Ignore non-Codable optional properties in Codable object 【发布时间】:2018-03-30 13:43:24 【问题描述】:

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

Ride struct 中,我们要跳过driver 属性的encodingdecoding,在解码时只保留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
    
  

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

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

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

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)

还有其他方法可以跳过可选属性吗?使用更大的模型会更容易。

【问题讨论】:

这是一个错误,请看这条评论链:***.com/questions/46104870/… 【参考方案1】:

尝试为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  /* ... */ 

快速测试:

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) */

顺便说一句,我使用了private CodingKeys,因为这也是编译器默认执行的操作;)

【讨论】:

打印的编译器错误对这个问题非常有帮助:note: cannot automatically synthesize 'Decodable' because 'driver' does not have a matching CodingKey and does not have a default value @mklbtz 好收获!可能是 Xcode 9.2 的改进...或者我们第一次完全错过了这个(有用的!)消息;)很多人甚至懒得阅读/解释这样的消息...

以上是关于忽略 Codable 对象中的非 Codable 可选属性的主要内容,如果未能解决你的问题,请参考以下文章

Codable和CodingKeys

Swift Codable 多种类型

使用 Codable 投射到对象

在 Swift 中实例化一个新的 Codable 对象的最简单方法是啥?

使用字典/数组初始化符合 Codable 的对象

Swift Codable:标记对象以进行状态恢复