如何从 Swift 中的自定义 encoded/decoded json 中删除数据模型 nil 字段
How to remove data model nil fields from custom encoded/decoded json in Swift
我正在尝试找到一种干净的方法来删除数据模型可选属性,如果在 Swift 中自定义 Encoding/Decoding 我的数据模型时 nil
。
我的用例:
import Foundation
public struct Message {
public let txnID: UUID
public var userId: String?
public var messageID: UUID?
public init(txnID: UUID, userId: String? = nil, messageID: UUID? = nil) {
self.txnID = txnID
self.userId = userId
self.messageID = messageID
}
}
extension Message: Codable {
private enum CodingKeys: CodingKey {
case txnID, userId, messageID
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
txnID = try container.decode(UUID.self, forKey: .txnID)
// FIXME: Remove `userId, messageID` if `nil`
self.userId = try? container.decode(String.self, forKey: .userId)
self.messageID = try? container.decode(UUID.self, forKey: .messageID)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.txnID, forKey: .txnID)
// FIXME: Remove `userId, messageID` if `nil`
try container.encode(self.userId, forKey: .userId)
try container.encode(self.messageID, forKey: .messageID)
}
}
/// The test case I have is basically is:
/// 1. Custom encode and decode my data model using `JSONEncoder` and `JSONDecoder`
/// 2. Remove optional attributes from the resulting encoded/decoded values
let msg = Message(txnID: UUID())
guard let encodedMsg = try? JSONEncoder().encode(msg), let jsonMessage = String(data: encodedMsg, encoding: String.Encoding.utf8) else {
fatalError()
}
// Now decode message
guard let origianlMsg = try? JSONDecoder().decode(Message.self, from: encodedMsg) else {
fatalError()
}
print("Encoded Message to json: \(jsonMessage)")
我在编码我的模型时得到以下 json
Encoded Message to json: {"txnID":"6211905C-8B72-4E19-81F0-F95F983F08CC","userId":null,"messageID":null}
但是,我想从我的 json 中删除 null 值。
Encoded Message to json: {"txnID":"50EFB999-C513-4DD0-BD3F-EEAE3F2304E9"}
我发现 decodeIfPresent
、encodeIfPresent
用于此用例。
try?
也不再用于验证这些字段(如果存在)。
extension Message: Codable {
private enum CodingKeys: CodingKey {
case txnID, userId, messageID
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
txnID = try container.decode(UUID.self, forKey: .txnID)
self.userId = try container.decodeIfPresent(String.self, forKey: .userId)
self.messageID = try container.decodeIfPresent(UUID.self, forKey: .messageID)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.txnID, forKey: .txnID)
try container.encodeIfPresent(self.userId, forKey: .userId)
try container.encodeIfPresent(self.messageID, forKey: .messageID)
}
}
我正在尝试找到一种干净的方法来删除数据模型可选属性,如果在 Swift 中自定义 Encoding/Decoding 我的数据模型时 nil
。
我的用例:
import Foundation
public struct Message {
public let txnID: UUID
public var userId: String?
public var messageID: UUID?
public init(txnID: UUID, userId: String? = nil, messageID: UUID? = nil) {
self.txnID = txnID
self.userId = userId
self.messageID = messageID
}
}
extension Message: Codable {
private enum CodingKeys: CodingKey {
case txnID, userId, messageID
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
txnID = try container.decode(UUID.self, forKey: .txnID)
// FIXME: Remove `userId, messageID` if `nil`
self.userId = try? container.decode(String.self, forKey: .userId)
self.messageID = try? container.decode(UUID.self, forKey: .messageID)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.txnID, forKey: .txnID)
// FIXME: Remove `userId, messageID` if `nil`
try container.encode(self.userId, forKey: .userId)
try container.encode(self.messageID, forKey: .messageID)
}
}
/// The test case I have is basically is:
/// 1. Custom encode and decode my data model using `JSONEncoder` and `JSONDecoder`
/// 2. Remove optional attributes from the resulting encoded/decoded values
let msg = Message(txnID: UUID())
guard let encodedMsg = try? JSONEncoder().encode(msg), let jsonMessage = String(data: encodedMsg, encoding: String.Encoding.utf8) else {
fatalError()
}
// Now decode message
guard let origianlMsg = try? JSONDecoder().decode(Message.self, from: encodedMsg) else {
fatalError()
}
print("Encoded Message to json: \(jsonMessage)")
我在编码我的模型时得到以下 json
Encoded Message to json: {"txnID":"6211905C-8B72-4E19-81F0-F95F983F08CC","userId":null,"messageID":null}
但是,我想从我的 json 中删除 null 值。
Encoded Message to json: {"txnID":"50EFB999-C513-4DD0-BD3F-EEAE3F2304E9"}
我发现 decodeIfPresent
、encodeIfPresent
用于此用例。
try?
也不再用于验证这些字段(如果存在)。
extension Message: Codable {
private enum CodingKeys: CodingKey {
case txnID, userId, messageID
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
txnID = try container.decode(UUID.self, forKey: .txnID)
self.userId = try container.decodeIfPresent(String.self, forKey: .userId)
self.messageID = try container.decodeIfPresent(UUID.self, forKey: .messageID)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.txnID, forKey: .txnID)
try container.encodeIfPresent(self.userId, forKey: .userId)
try container.encodeIfPresent(self.messageID, forKey: .messageID)
}
}