jup*_*p0r 2 ruby serialization datetime
我想将Ruby DateTime对象序列化为json.不幸的是,我的方法不是对称的:
require 'date'
date = DateTime.now
DateTime.parse(date.to_s) == date
=> false
Run Code Online (Sandbox Code Playgroud)
我可以使用一些任意的strftime/parse字符串组合,但我相信必须有一个更好的方法.
不幸的是,接受的答案并不是一个好的解决方案.与往常一样,marshal/unmarshal是一种工具,你只能作为最后的手段,但在这种情况下,它可能会破坏你的应用程序.
OP特别提到将日期序列化为JSON.根据RFC 7159:
JSON文本应以UTF-8,UTF-16或UTF-32编码.默认编码是UTF-8,以UTF-8编码的JSON文本是可互操作的,因为它们将通过最大数量的实现成功读取; 有许多实现无法成功读取其他编码中的文本(例如UTF-16和UTF-32).
现在让我们来看看我们从Marshal得到的东西:
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
Run Code Online (Sandbox Code Playgroud)
除了返回一个非人类可读Marshal.dump的值之外,还为我们提供了一个无法转换为UTF-8的值.这意味着将它放入(有效)JSON的唯一方法是以某种方式对其进行编码,例如base-64.
没有必要这样做.已经有一种非常可互操作的方式来表示日期和时间:ISO 8601.我不会过去为什么它是JSON(以及一般)的最佳选择,但这里的答案很好地涵盖了它:"正确的"JSON日期格式.
从Ruby 1.9.3开始,DateTime类分别具有分析和格式化ISO 8601日期的iso8601 类和实例方法.后者采用参数来指定小数秒的精度(例如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
Run Code Online (Sandbox Code Playgroud)
请注意,如果指定较小的精度,则可能不起作用,因为例如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"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6868 次 |
| 最近记录: |