[英]Is it possible yet to use Decodable with Firestore Timestamps/Dates?
I have a dictionary that's a [String: Bookmark]
but that createdAt is saved as a Timestamp
and the decoder throws an error when trying to make sense of the Date
我有一个
[String: Bookmark]
字典,但createdAt被保存为Timestamp
,并且解码器在试图理解Date
时抛出错误
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (__NSDate)'
***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'JSON写入中的类型无效(__NSDate)'
struct Bookmark: Decodable {
let messageId: String
let messageCreatedAt: Date
}
JSONDecoder().decode([String: Bookmark].self, data: data)
Is there a way yet to make Swift's Decodable
protocol play nicely with Firestore Timestamps? 有没有一种方法可以使Swift的
Decodable
协议与Firestore Timestamps完美配合?
Edit: 编辑:
If I print the [String: Any]
and then try to decode in the console like so 如果我打印
[String: Any]
,然后尝试在控制台中像这样解码
▿ 1 : 2 elements
- key : "messageCreatedAt"
- value : 2018-11-27 20:59:11 +0000
po valueDict["messageCreatedAt"] as? Date
I get 我懂了
▿ Optional<Date>
▿ some : 2018-11-27 20:59:11 +0000
- timeIntervalSinceReferenceDate : 565045151.531769
So it must be something in Decodable
then that isn't able to identify and parse this? 因此,它一定是“可
Decodable
中无法识别和解析的东西吗?
Edit: 编辑:
JSON is JSON是
{
"messageId": "abc123",
"messageCreatedAt": "2018-11-27 20:59:11 +0000"
}
How is JSONDecoder
is decoding dates is defined by value of .dateDecodingStrategy
property. JSONDecoder
如何解码日期由.dateDecodingStrategy
属性的值定义。
If you have to parse Date
from a string you should use either .iso8601
or .formatted(_:)
(or if your date format is really custom and complicated and/or weird you may to have use .custom(_:)
). 如果必须从字符串中解析
Date
,则应使用.iso8601
或.formatted(_:)
(或者,如果日期格式确实是自定义的,复杂和/或怪异的,则可以使用.custom(_:)
)。
Your date string is almost ISO 8601
formatted (it only lacks T
between date and time parts), but that's enough to fail. 您的日期字符串几乎采用
ISO 8601
格式(日期和时间部分之间仅缺少T
),但这足以失败。
So your best option here is to use formatted(_:)
: 因此,这里最好的选择是使用
formatted(_:)
:
// Declare it somewhere and reuse single instance as much as possible, formatter initialization is quite expensive
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX") // Better to fix Locale here
dateFormatter.dateFormat = "yyyy-MM-dd kk:mm:ss Z"
And then 接着
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)
let bookmark = try decoder.decode(Bookmark.self, from: data)
print(bookmark.messageCreatedAt, bookmark.messageCreatedAt.timeIntervalSince1970)
// prints "2018-11-27 20:59:11 +0000 1543352351.0"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.