Swift 4.1可编码采用数组到key = value(键包含一个值)

时间:2018-06-02 08:48:40

标签: swift swift4

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

enter image description here

正如你可以看到它的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()
    }

}

1 个答案:

答案 0 :(得分:2)

你很亲密;你已经找到了最棘手的部分,就是如何将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))
        }
    }
}