忽略 Codable 对象中的非 Codable 可选属性
Ignore non-Codable optional properties in Codable object
当符合Codable
协议时,我不能轻易跳过可选的属性 of non-Codable class
在 Ride
结构中,我们要跳过 encoding 和 decoding of 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
}
}
在这种情况下我得到一个编译错误
Type 'Driver' does not conform to protocol 'Decodable'
到目前为止,我唯一的解决方案是通过提供以下方法手动编码和解码:
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)
}
还有其他方法可以跳过可选的 属性 吗?使用更大的模型会容易得多。
尝试为 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
因为这也是编译器默认做的 ;)
当符合Codable
协议时,我不能轻易跳过可选的属性 of non-Codable class
在 Ride
结构中,我们要跳过 encoding 和 decoding of 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
}
}
在这种情况下我得到一个编译错误
Type 'Driver' does not conform to protocol 'Decodable'
到目前为止,我唯一的解决方案是通过提供以下方法手动编码和解码:
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)
}
还有其他方法可以跳过可选的 属性 吗?使用更大的模型会容易得多。
尝试为 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
因为这也是编译器默认做的 ;)