【问题标题】:Swift 4.1 codable adoption for array to key = value (key contains a value)Swift 4.1 可编码采用数组到键 = 值(键包含一个值)
【发布时间】:2018-06-02 08:48:39
【问题描述】:

如何使用 Swift Codable 协议将存储在 Swift 中的数据作为对象数组(只有 2 个值)解码/编码为(JSON 或其他类型的数据表示;应该无关紧要)key = value结构如下:

如您所见,它是一个timestamp = value 符号结构(我对时间戳的格式没有任何问题,没关系)

(我知道之前已经回答过关于存储在键中的数据的问题,但是我的问题不同,因为它特定于对象数组,只有 2 个值在平面键 = 值结构中转码)。

这是我处理 2 个对象的代码:

MetricResult = 包含时间戳和测量值

MetricResults = 包含应正确编码的 MetricResult 数组。

我已经为MetricResult 进行了编码,但是在阅读时我不知道如何处理包含实际数据本身的变量键。

struct MetricResult : Codable {
    var date   = Date()
    var result = Int(0)

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: Date.self)
        try container.encode(result, forKey: date)
    }

    init(from decoder: Decoder) throws {
        //how do deal with variable key name here??
    }
}

struct MetricResults: Codable {

    var results = [MetricResult]()

    func encode(to encoder: Encoder) throws {
        //how do deal with variable key name here??
    }

    init(from decoder: Decoder) throws {
        //how do deal with variable key name here??
    }
}

extension Date: CodingKey {

    //MARK: - CodingKey compliance

    public init?(intValue: Int)       {
        return nil
    }

    public init?(stringValue: String) {
        self.init(stringFirebase: stringValue)
    }

    public var intValue: Int?{
        return nil
    }

    public var stringValue: String {
        return stringFirebase()
    }

}

【问题讨论】:

    标签: swift swift4


    【解决方案1】:

    你很亲密;您已经解决了最棘手的部分,即如何将 Date 转换为 CodingKey(请务必将此标记为 private;系统的其他部分可能也希望以另一种方式将 Date 用作 CodingKey)。

    主要问题是在这个规范中,MetricResult 本身不能是 Codable。你不能只编码“一个键值对”。那只能被编码为某些东西(即字典)的一部分。所有的编码/解码都必须由 MetricResults 以这种方式完成:

    extension MetricResults: Codable {
        func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: Date.self)
            for result in results {
                try container.encode(result.result, forKey: result.date)
            }
        }
    
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: Date.self)
            for date in container.allKeys {
                let result = try container.decode(Int.self, forKey: date)
                results.append(MetricResult(date: date, result: result))
            }
        }
    }
    

    【讨论】:

    • 很有魅力!我错过了 allKeys 的可用性。感谢罗布的精彩回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多