如何使用Ruby自动将JSON时间字符串转换为Time对象?

Sea*_*bry 1 ruby time json ruby-on-rails

当我使用Ruby来使用返回JSON中的时间字符串的Web服务API时,我希望它们自动转换为Time对象(或DateTime对象),这样我就不会自己手动执行.

例如,我想要输出Time而不是String:

irb(main):001:0> require 'json'
=> true
irb(main):002:0> payload = JSON.generate({ now: Time.now })
=> "{\"now\":\"2018-04-02 13:15:56 -0500\"}"
irb(main):003:0> JSON.parse(payload)['now'].class
=> String
Run Code Online (Sandbox Code Playgroud)

我知道时间不是JSON规范的一部分.我只是想知道是否有办法配置Ruby的stdlib JSON解析器来自动解析日期,或者是否有一个库为你做这个.

Sea*_*bry 6

设置时,Active Support可以自动将ISO 8601格式的时间转换为ActiveSupport::TimeWithZone对象ActiveSupport.parse_json_times = true.

http://api.rubyonrails.org/classes/ActiveSupport/JSON.html

#!/usr/bin/env ruby

require 'active_support/json'
require 'active_support/time'

Time.zone = 'UTC'
ActiveSupport.parse_json_times = true

puts payload1 = JSON.generate({ now: Time.now })
puts payload2 = ActiveSupport::JSON.encode({ now: Time.now })

puts ActiveSupport::JSON.decode(payload1)['now'].class
puts ActiveSupport::JSON.decode(payload2)['now'].class
Run Code Online (Sandbox Code Playgroud)

哪个会输出:

{"now":"2018-04-02 13:19:40 -0500"}
{"now":"2018-04-02T13:19:40.291-05:00"}
String
ActiveSupport::TimeWithZone
Run Code Online (Sandbox Code Playgroud)

注意Active Stdlib的默认时间是如何被Active Support解析的.仅成功转换ISO 8601格式化时间.Active Support 使用正则表达式来检测时间.您可以阅读测试以了解它支持的时间格式.看起来它支持ISO 8601,但支持Unix/POSIX /大纪元时间戳.

当我针对Rails创建此问题时,我被告知Active Support中的此功能.

一些历史:时间解析曾经是Rails中的默认行为,但后来ActiveSupport.parse_json_times被添加到想要关闭它的人,然后它默认关闭,所以现在你必须选择它.