【问题标题】:How to remove data model nil fields from custom encoded/decoded json in Swift如何从 Swift 中的自定义编码/解码 json 中删除数据模型 nil 字段
【发布时间】:2019-11-11 23:12:26
【问题描述】:

当在 Swift 中自定义编码/解码我的数据模型时,如果它的 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 值以获得 nil 值。

Encoded Message to json: {"txnID":"50EFB999-C513-4DD0-BD3F-EEAE3F2304E9"}

【问题讨论】:

  • 修剪是什么意思?从解码对象中删除?
  • 是的,没错
  • 实施description 以满足您的需求。
  • 这里说“编码”是什么意思?您在此处显示的字符串不是众所周知的编码器(JSON、Plist)可以生成的任何内容,那么您是如何“编码”它的呢?这些看起来像 print 的输出(正如 rmaddy 所说,它通常与 CustomStringConvertible 相关联),但这与 Codable 无关。
  • 我更新了我的问题作为游乐场的更多细节。我正在尝试找到一种干净的方法来从我的 json 中删除 nil 值。

标签: swift codable decodable


【解决方案1】:

我发现decodeIfPresentencodeIfPresent 用于此用例。

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)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-16
    • 2021-01-11
    • 1970-01-01
    • 2016-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    相关资源
    最近更新 更多