Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby objects and JSON serialization (without Rails)

I'm trying to understand the JSON serialization landscape in Ruby. I'm new to Ruby.

Is there any good JSON serialization options if you are not working with Rails?

That seems to be where this answer goes (to Rails) How to convert a Ruby object to JSON

The json gem seems to make it look like you have to write your own to_json method. I haven't been able to get to_json to work with arrays and hashes (documentation says it works with these) Is there a reason the json gem doesn't just reflect over the object and use a default serialization strategy? Isn't this how to_yaml works (guessing here)

like image 737
BuddyJoe Avatar asked Dec 16 '10 18:12

BuddyJoe


People also ask

How do you serialize an object in Ruby?

The Marshal Module As Ruby is a fully object oriented programming language, it provides a way to serialize and store objects using the Marshall module in its standard library. It allows you to serialize an object to a byte stream that can be stored and deserialized in another Ruby process.

How do you turn a Ruby object into JSON?

Yes, you can do it with to_json . You may need to require 'json' if you're not running Rails. With Rails it's not necessary to use require 'json' , but with regular Ruby code it's likely to be necessary. JSON is part of Ruby's Standard Library so it comes with the language.

What is the difference between JSON and serialization?

JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object). If you serialize this result it will generate a text with the structure and the record returned.

What is difference between Stringify and serialize?

stringify() ignores functions/methods when serializing. JSON also can't encode circular references. Most other serialization formats have this limitation as well but since JSON looks like javascript syntax some people assume it can do what javascript object literals can.


2 Answers

For the JSON library to be available, you may have to install libjson-ruby from your package manager.

To use the 'json' library:

require 'json' 

To convert an object to JSON (these 3 ways are equivalent):

JSON.dump object #returns a JSON string JSON.generate object #returns a JSON string object.to_json #returns a JSON string 

To convert JSON text to an object (these 2 ways are equivalent):

JSON.load string #returns an object JSON.parse string #returns an object 

It will be a bit more difficult for objects from your own classes. For the following class, to_json will produce something like "\"#<A:0xb76e5728>\"".

class A     def initialize a=[1,2,3], b='hello'         @a = a         @b = b     end end 

This probably isn't desirable. To effectively serialise your object as JSON, you should create your own to_json method. To go with this, a from_json class method would be useful. You could extend your class like so:

class A     def to_json         {'a' => @a, 'b' => @b}.to_json     end     def self.from_json string         data = JSON.load string         self.new data['a'], data['b']     end end 

You could automate this by inheriting from a 'JSONable' class:

class JSONable     def to_json         hash = {}         self.instance_variables.each do |var|             hash[var] = self.instance_variable_get var         end         hash.to_json     end     def from_json! string         JSON.load(string).each do |var, val|             self.instance_variable_set var, val         end     end end 

Then you can use object.to_json to serialise to JSON and object.from_json! string to copy the saved state that was saved as the JSON string to the object.

like image 59
david4dev Avatar answered Sep 17 '22 16:09

david4dev


Check out Oj. There are gotchas when it comes to converting any old object to JSON, but Oj can do it.

require 'oj'  class A     def initialize a=[1,2,3], b='hello'         @a = a         @b = b     end end  a = A.new puts Oj::dump a, :indent => 2 

This outputs:

{   "^o":"A",   "a":[     1,     2,     3   ],  "b":"hello" } 

Note that ^o is used to designate the object's class, and is there to aid deserialization. To omit ^o, use :compat mode:

puts Oj::dump a, :indent => 2, :mode => :compat 

Output:

{   "a":[     1,     2,     3   ],   "b":"hello" } 
like image 38
Jimothy Avatar answered Sep 18 '22 16:09

Jimothy