简体   繁体   English

是否可以在Firestore时间戳/日期中使用“可解码”?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM