首页 > 解决方案 > Swift 4.1 可编码采用数组到键 = 值(键包含一个值)

问题描述

如何使用 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()
    }

}

标签: swiftswift4

解决方案


你很亲近;您已经解决了最棘手的部分,即如何将 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))
        }
    }
}

推荐阅读