我正在尝试在Swift中使用Codables
解码以下JSON字符串。
let json = """
{
"todaysProvision": 235.50,
"referenceDate": "2019-01-30",
"lastSevenDays": {
"2019-02-12": 235.20,
"2019-02-11": 235.20,
"2019-02-10": 235.20,
"2019-02-09": 235.20,
"2019-02-08": 235.20,
"2019-02-07": 235.20,
"2019-02-06": 235.20,
}
}
"""
我当前的解码结构看起来像这样。
struct ProvisionInfo: Codable {
let todaysProvision: Double
let referenceDate: Date
}
将JSONDecoder
与dateDecodingStrategy
一起使用就像键referenceDate
的一种魅力:
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(df)
let decoded = try decoder.decode(ProvisionInfo.self, from: json.data(using: .utf8)!)
// decoded.todaysProvision -> 235.5
// decoded.referenceDate -> "Jan 30, 2019 at 12:00 AM"
对于JSON字典lastSevenDays
,我想可以将结构更改为
struct ProvisionInfo: Codable {
let todaysProvision: Double
let referenceDate: Date
let lastSevenDays: [Date: Double]
}
但是,这样我得到了解码错误
Playground execution terminated: An error was thrown and was not caught:
▿ DecodingError
▿ typeMismatch : 2 elements
- .0 : Swift.Array<Any>
▿ .1 : Context
▿ codingPath : 1 element
- 0 : CodingKeys(stringValue: "lastSevenDays", intValue: nil)
- debugDescription : "Expected to decode Array<Any> but found a dictionary instead."
- underlyingError : nil
解决此问题的唯一方法是添加一个自定义初始化程序来解码我的结构,该初始化程序将字典解析为[String: Double]
并使用相同的[Date: Double]
将该字典转换为DateFormatter
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
todaysProvision = try container.decode(Double.self, forKey: .todaysProvision)
referenceDate = try container.decode(Date.self, forKey: .referenceDate)
let foo = try container.decode([String: Double].self, forKey: .lastSevenDays)
lastSevenDays = Dictionary(uniqueKeysWithValues:foo.compactMap { (key, value) in
guard let date = df.date(from: key) else { return nil }
return (date, value)
})
}
这是使用[Date: Double]
解析Codables
的唯一可能方法,还是我做错了什么?
谢谢!