首页 > 解决方案 > 解码/编码以日期为键的字典

问题描述

尝试对具有Dateas 键的字典进行编码/解码会产生一些令人惊讶的结果。

以下代码说明了该行为:

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基础设施一起工作?

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

标签: swiftcodable

解决方案


CodingKeyRepresentable在 Swift 5.6 中引入,现在允许Date使用Codable.

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

Swift 5.6的发布日期尚未确定,但发布分支已经被削减。


推荐阅读