Path: | lib/json.rb |
Last Update: | Fri Aug 25 00:27:07 UTC 2006 |
Florian Frank <flori@ping.de>
This is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 2 as published by the Free Software Foundation: www.gnu.org/copyleft/gpl.html
The latest version of this library can be downloaded at
Online Documentation should be located at
To create a JSON string from a ruby data structure, you can call JSON.unparse like that:
json = JSON.unparse [1, 2, {"a"=>3.141}, false, true, nil, 4..10] # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
It’s also possible to call the to_json method directly.
json = [1, 2, {"a"=>3.141}, false, true, nil, 4..10].to_json # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
To get back a ruby data structure, you have to call JSON.parse on the JSON string:
JSON.parse json # => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
Note, that the range from the original data structure is a simple string now. The reason for this is, that JSON doesn’t support ranges or arbitrary classes. In this case the json library falls back to call Object#to_json, which is the same as to_s.to_json.
It’s possible to extend JSON to support serialization of arbitray classes by simply implementing a more specialized version of the to_json method, that should return a JSON object (a hash converted to JSON with to_json) like this (don’t forget the *a for all the arguments):
class Range def to_json(*a) { 'json_class' => self.class.name, 'data' => [ first, last, exclude_end? ] }.to_json(*a) end end
The hash key ‘json_class’ is the class, that will be asked to deserialize the JSON representation later. In this case it’s ‘Range’, but any namespace of the form ‘A::B’ or ’::A::B’ will do. All other keys are arbitrary and can be used to store the necessary data to configure the object to be deserialized.
If a the key ‘json_class’ is found in a JSON object, the JSON parser checks if the given class responds to the json_create class method. If so, it is called with the JSON object converted to a Ruby hash. So a range can be deserialized by implementing Range.json_create like this:
class Range def self.json_create(o) new(*o['data']) end end
Now it possible to serialize/deserialize ranges as well:
json = JSON.unparse [1, 2, {"a"=>3.141}, false, true, nil, 4..10] # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]" JSON.parse json # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
JSON.unparse always creates the shortes possible string representation of a ruby data structure in one line. This good for data storage or network protocols, but not so good for humans to read. Fortunately there’s also JSON.pretty_unparse that creates a more readable output:
puts JSON.pretty_unparse([1, 2, {"a"=>3.141}, false, true, nil, 4..10]) [ 1, 2, { "a": 3.141 }, false, true, null, { "json_class": "Range", "data": [ 4, 10, false ] } ]
There are also the methods Kernel#j for unparse, and Kernel#jj for pretty_unparse output to the console, that work analogous to Kernel#p and Kernel#pp.