我想將Ruby DateTime對象序列化爲json。不幸的是,我的方法不是對稱的:我可以使用一些任意的strftime/parse字符串組合,但我相信必須有更好的方法。DateTime序列化和反序列化
回答
不幸的是,接受的答案不是一個好的解決方案。像往常一樣,編組/解組是一種工具,你應該只用作最後的手段,但在這種情況下,它可能會破壞你的應用程序。
OP明確提到將日期序列化爲JSON。每RFC 7159:
JSON文本應以UTF-8,UTF-16或UTF-32編碼。默認編碼是UTF-8,以UTF-8編碼的JSON文本是可互操作的,因爲它們將通過最大數量的實現成功讀取;有很多實現無法成功讀取其他編碼中的文本(如UTF-16和UTF-32)。
現在讓我們來看看我們從元帥得到:
marsh = Marshal.dump(DateTime.now)
# => "\x04\bU:\rDateTime[\vi\x00i\x03\xE0\x7F%i\x02s\xC9i\x04\xF8z\xF1\"i\xFE\xB0\xB9f\f2299161"
puts marsh.encoding
# -> #<Encoding:ASCII-8BIT>
marsh.encode(Encoding::UTF_8)
# -> Encoding::UndefinedConversionError: "\xE0" from ASCII-8BIT to UTF-8
除了返回的值是不是人類可讀,Marshal.dump
給了我們不能轉換爲UTF值-8。這意味着將其放入(有效)JSON的唯一方法是以某種方式對其進行編碼,例如,基64。
沒有必要這樣做。已經有一種可以互操作的方式來表示日期和時間:ISO 8601。我不會回顧爲什麼它是JSON的最佳選擇(一般而言),但這裏的答案覆蓋了它:The "right" JSON date format。
由於Ruby 1.9.3的DateTime類已分別有iso8601
class和instance方法分析和格式化ISO 8601日期。後者採用參數來指定小數秒的精度(例如,3
爲毫秒):
require "date"
date = DateTime.now
str = date.iso8601(9)
puts str
# -> 2016-06-28T09:35:58.311527000-05:00
DateTime.iso8601(str) == date
# => true
注意,如果你指定一個較小的精度,這可能不行,因爲如58.311
不等於58.311527
。精確度爲9
(納秒)對我來說似乎是安全的,因爲DateTime文檔說:
小數的精度假定在最大納秒。
但是,如果您正在與可能使用更高精度的系統進行互操作,則應考慮這一點。
最後,如果你想使Ruby的JSON庫自動使用iso8601
系列化,覆蓋as_json
和to_json
方法:
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
require 'date'
class DateTime
def as_json(*)
iso8601(9)
end
def to_json(*args)
as_json.to_json(*args)
end
end
puts DateTime.now.to_json
# -> "2016-06-28T09:35:58.311527000-05:00"
這是因爲date
有次秒值,並且#to_s
方法會以秒爲單位返回ISO時間格式,比較不成功。
1.9.3p327 :021 > date = DateTime.now
=> #<DateTime: 2012-11-28T07:32:40+09:00 ((2456259j,81160s,283019000n),+32400s,2299161j)>
1.9.3p327 :022 > DateTime.parse(date.to_s)
=> #<DateTime: 2012-11-28T07:32:40+09:00 ((2456259j,81160s,0n),+32400s,2299161j)>
所以他們實際上是不同的。
如果你不關心亞秒,只是忘記比較是否成功。
或者,您可以使用DateTime#marshal_load
和DateTime#marshal_dump
作爲1.9.3。 (我不知道這一點到現在..)
它的工作:
date1 = DateTime.now
dump = date1.marshal_dump
date2 = DateTime.new.marshal_load(dump)
date1 == date2 # => true
無論是to_s
方法和to_json
方法(提供require 'json'
)忽略它們由DateTime對象存儲在納秒date
。好老Marshal
發送:
require 'date'
date = DateTime.now
m_date = Marshal.dump(date)
p Marshal.load(m_date) == date # => true
- 1. JSon反序列化DateTime
- 2. XmlSerializer不反序列化DateTime
- 3. 序列化和反序列化一個DateTime字符串在UTC
- 4. java序列化和反序列化
- 5. 序列化和反序列化
- 6. Spring Remoting序列化和反序列化
- 7. WCF序列化和反序列化
- 8. OData序列化和反序列化
- 9. jQuery序列化和反序列化
- 10. Hadoop序列化和反序列化
- 11. JQuery序列化和反序列化
- 12. PHP序列化和反序列化
- 13. 性狀和序列化/反序列化
- 14. 序列化和反序列化(C#)
- 15. 序列化和反序列化
- 16. 序列化和反序列化
- 17. C#Xml序列化和反序列化
- 18. 序列化/反序列化和Proguard
- 19. 序列化和反序列化
- 20. 序列化和反序列化
- 21. DateTime的WebApi序列化 - 如何反序列化?
- 22. 反序列化反序列化接口
- 23. JSON反序列化不反序列化?
- 24. 反序列化和排序
- 25. 序列化/反序列化DataContracts列表
- 26. Json.NET:序列化/反序列化陣列
- 27. XML反序列化的DateTime格式
- 28. json.net反序列化對象中的datetime
- 29. JavaScriptSerializer非反序列化DateTime/TimeSpan正確
- 30. 休息夏普的DateTime反序列化
感謝您詳細的分析,我是不知道的問題,使用UTF-8 – jupp0r