忽略 swift Codable 中的以下属性?
ignore the following properties in swift Codable?
我有这个帐户结构。当我发送“POST”端点并使用它们return成功解码到swift对象[=12时,我想忽略以下属性环境和编码到JSON对象的Id =]
更新我有这个错误 属性 类型 '[Environment]' 与它的包装类型 'wrappedValue' 属性 不匹配 'SkipEncode'
struct Account: Codable {
let accountID, displayName, managedByID, id: String
let environments: [Environment]
let contacts: [Contact]
enum CodingKeys: String, CodingKey {
case accountID
case displayName
case managedID
case id
case environments
case contacts
}
}
如果要忽略,比如environments
编码的时候,可以定义自己的编码实现:
struct Account: Codable {
let accountID, displayName, managedByID, id: String
let environments: [Environment]
let contacts: [Contact]
enum CodingKeys: String, CodingKey {
case accountID, displayName, managedByID, id, environments, contacts
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(accountID, forKey: .accountID)
try container.encode(displayName, forKey: .displayName)
// ... just don't include the environments here
}
}
另一种方法,如果您不想手动实现 encode(to:)
并放弃 Codable
自动合成的好处,您可以创建一个 属性 包装器作为一种方式标记要跳过的属性:
@propertyWrapper
struct SkipEncode<T> {
var wrappedValue: T
}
extension SkipEncode: Decodable where T: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.wrappedValue = try container.decode(T.self)
}
}
extension SkipEncode: Encodable {
func encode(to encoder: Encoder) throws {
// nothing to do here
}
}
extension KeyedEncodingContainer {
mutating func encode<T>(_ value: SkipEncode<T>, forKey key: K) throws {
// overload, but do nothing
}
}
那么你可以像这样使用 @SkipEncode
:
struct Account: Codable {
let accountID, displayName, managedByID: String
let contacts: [Contact]
@SkipEncode
let id: String
@SkipEncode
let environments: [Environment]
}
按照 NewDev 建议的方法跟进。如果你想实现一个 属性 包装器,你需要实现一个通用的包装器才能跳过任何 属性,而不仅仅是字符串:
@propertyWrapper
struct SkipEncode<T: Decodable> {
var wrappedValue: T
}
extension SkipEncode: Codable {
init(from decoder: Decoder) throws {
wrappedValue = try decoder.singleValueContainer().decode(T.self)
}
func encode(to encoder: Encoder) throws { }
}
extension KeyedEncodingContainer {
mutating func encode<T>(_ value: SkipEncode<T>, forKey key: K) throws { }
}
游乐场测试:
结构环境:可编码{}
结构联系人:Codable { }
struct Account: Codable {
let accountID, displayName, managedByID: String
@SkipEncode
var id: String
@SkipEncode
var environments: [Environment]
let contacts: [Contact]
}
let account = Account.init(accountID: "account", displayName: "name", managedByID: "manager", id: "id", environments: [], contacts: [])
let dt = try JSONEncoder().encode(account)
print(String.init(data: dt, encoding: .utf8)!) // {"accountID":"account","contacts":[],"managedByID":"manager","displayName":"name"}
我有这个帐户结构。当我发送“POST”端点并使用它们return成功解码到swift对象[=12时,我想忽略以下属性环境和编码到JSON对象的Id =]
更新我有这个错误 属性 类型 '[Environment]' 与它的包装类型 'wrappedValue' 属性 不匹配 'SkipEncode'
struct Account: Codable {
let accountID, displayName, managedByID, id: String
let environments: [Environment]
let contacts: [Contact]
enum CodingKeys: String, CodingKey {
case accountID
case displayName
case managedID
case id
case environments
case contacts
}
}
如果要忽略,比如environments
编码的时候,可以定义自己的编码实现:
struct Account: Codable {
let accountID, displayName, managedByID, id: String
let environments: [Environment]
let contacts: [Contact]
enum CodingKeys: String, CodingKey {
case accountID, displayName, managedByID, id, environments, contacts
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(accountID, forKey: .accountID)
try container.encode(displayName, forKey: .displayName)
// ... just don't include the environments here
}
}
另一种方法,如果您不想手动实现 encode(to:)
并放弃 Codable
自动合成的好处,您可以创建一个 属性 包装器作为一种方式标记要跳过的属性:
@propertyWrapper
struct SkipEncode<T> {
var wrappedValue: T
}
extension SkipEncode: Decodable where T: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.wrappedValue = try container.decode(T.self)
}
}
extension SkipEncode: Encodable {
func encode(to encoder: Encoder) throws {
// nothing to do here
}
}
extension KeyedEncodingContainer {
mutating func encode<T>(_ value: SkipEncode<T>, forKey key: K) throws {
// overload, but do nothing
}
}
那么你可以像这样使用 @SkipEncode
:
struct Account: Codable {
let accountID, displayName, managedByID: String
let contacts: [Contact]
@SkipEncode
let id: String
@SkipEncode
let environments: [Environment]
}
按照 NewDev 建议的方法跟进。如果你想实现一个 属性 包装器,你需要实现一个通用的包装器才能跳过任何 属性,而不仅仅是字符串:
@propertyWrapper
struct SkipEncode<T: Decodable> {
var wrappedValue: T
}
extension SkipEncode: Codable {
init(from decoder: Decoder) throws {
wrappedValue = try decoder.singleValueContainer().decode(T.self)
}
func encode(to encoder: Encoder) throws { }
}
extension KeyedEncodingContainer {
mutating func encode<T>(_ value: SkipEncode<T>, forKey key: K) throws { }
}
游乐场测试:
结构环境:可编码{} 结构联系人:Codable { }
struct Account: Codable {
let accountID, displayName, managedByID: String
@SkipEncode
var id: String
@SkipEncode
var environments: [Environment]
let contacts: [Contact]
}
let account = Account.init(accountID: "account", displayName: "name", managedByID: "manager", id: "id", environments: [], contacts: [])
let dt = try JSONEncoder().encode(account)
print(String.init(data: dt, encoding: .utf8)!) // {"accountID":"account","contacts":[],"managedByID":"manager","displayName":"name"}