Ruby JSON convert Time

So I just noticed that when parsing JSON Time objects end up as strings.

a = { 'time' => Time.now }
b = JSON.parse(a.to_json)
puts "a is a #{a['time'].class} object."
puts "b is a #{b['time'].class} object."
#< a is a Time object.
#< b is a String object.

What is the best way to work around this? The only way I can think of requires parsing each value.

require 'time'
a = { 'time' => Time.now }
b = JSON.parse(a.to_json)
b['time'] = Time.parse(b['time'])
puts "a is a #{a['time'].class} object."
puts "b is a #{b['time'].class} object."
#< a is a Time object.
#< b is a Time object.

Update; Ok from a bit more searching it doesn’t look like there is an easy fix available.

Basically, you do not store the Time object, you store the number of it’s seconds since to start of the epoch. You can use #to_i (or #to_f if you want to be more precise than integer seconds.)

t = Time.now
a = { 'time' => t.to_i }
j = a.to_json
# Send to a Html Dialog,
# Later get it back:
b = JSON.parse(j)
t = Time::at(b['time'])
1 Like

JSON supports strings, null, true, false and numbers, as well as arrays and hashmaps/objects containing these types of elements. Time, Sketchup::Material and other kind of objects need to be serialized into the supported units.

2 Likes

That makes perfect sense. I guess now that I think of it, I was already doing that with lengths.

hash['length'].to_l
1 Like

We have discussed in the past some SketchUp API additions to the JSON library.

See:
Module JSON: Extended rendering and loading of Ruby objects