Decode/encode 按日期键入的字典

Decode/encode dictionary keyed by Date

尝试 encode/decode 一个以 Date 作为键的字典,会产生一些令人惊讶的结果。

以下代码说明了该行为:

let data = """
{ "20210507": "Person1", "20210508": "Person2" }
""".data(using: .utf8)!

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMdd"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)

try print(decoder.decode([Date: String].self, from: data))

天真地,人们会认为解码会成功,但事实并非如此,我们会抛出以下错误:

Fatal error: Error raised at top level: Swift.DecodingError.typeMismatch(Swift.Array<Any>,
Swift.DecodingError.Context(codingPath: [], 
debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))

所以解码器被告知解码一个字典,它以某种方式期望一个数组。

转到编码端:

let dict: [Date: String] = [Date(): "Person1",
                            Date().addingTimeInterval(86400): "Person2"]

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMdd"

let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .formatted(dateFormatter)

let data = try encoder.encode(dict)
print(String(data: data, encoding: .utf8)!)

这有效,但输出如下:

["20211007","Person1","20211008","Person2"]

,这解释了之前尝试解码字典(又名 JSON 对象)时收到的错误。

为了确定行为,我将解码数据替换为

["20210507", "Person1", "20210508", "Person2"]

,解码成功,第一个片段的解码代码没有其他变化。

因此,似乎在将日期作为字典键处理时,解码器需要键+值对数组,而不是字典。

有没有办法让它与标准 Codable 基础设施一起工作?

另一种方法是解码 [String: String],然后解析日期,想知道是否有更清晰、更“Codabe 式”的替代方法。

CodingKeyRepresentable 在 Swift 5.6 中引入,现在允许 decoding/encoding Date 键控字典使用 Codable.

有关详细信息,请参阅 SE-0320

尚未为 Swift 5.6 设置发布日期,但发布分支已被删除。