Reputation: 1057
When I’m using Ruby to consume a web service API that returns time strings in JSON, I want them automatically converted into Time
objects (or DateTime
objects) so that I don’t have do it manually myself.
For example, I want this to output Time
instead of 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
I understand that times are not part of the JSON spec. I’m just wondering if there’s a way to configure Ruby’s stdlib JSON parser to automatically parse dates, or if there’s a library that does this for you.
Upvotes: 2
Views: 2437
Reputation: 1057
Active Support can automatically convert ISO 8601 formatted times into ActiveSupport::TimeWithZone
objects when you set 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
Which will output:
{"now":"2018-04-02 13:19:40 -0500"}
{"now":"2018-04-02T13:19:40.291-05:00"}
String
ActiveSupport::TimeWithZone
Notice how Ruby stdlib’s default time is not parseable by Active Support. Only the ISO 8601 formatted time gets successfully converted. Active Support uses a regex to detect times. You can read the tests to get a good idea of the time formats that it supports. Looks like it supports ISO 8601, but does not support Unix/POSIX/Epoch timestamps.
I was informed of this feature in Active Support when I created this issue against Rails.
Some history: Time parsing used to be the default behavior in Rails, but then ActiveSupport.parse_json_times
was added for people who wanted to turn it off, and then it became turned off by default, so now you have to opt into it.
Upvotes: 10