//
you're reading...
Ruby

Initialize Objects from a hierarchy of hashes (JSON format) in Ruby

There are some nice little functions to initialize Objects in Ruby from a hash. A good example could be found here.

But sometimes, when we read an external API (XML or JSON) and parse the result, we get data which is a set of nested hashes and arrays. Then we want to initialize an object in our application with this data. I wrote the following module to do that.

init_from_hash.rb
-----------------------------
module InitFromHash

def initialize(*args)
args.first.each do |k, v|
unless defined?(k).nil? # check if it's included as a reader attribute
result = v.instance_of?(Array) ? v.inject([]) {|arr, v1| arr << init_object(v1, k)} : init_object(v, k)
instance_variable_set("@#{k}", result)
end
end if (args.length == 1 && args.first.is_a?(Hash))
end

def init_object value, klass
value.instance_of?(Hash) ? (get_module_name + klass.to_s.capitalize).constantize.new(value) : value
end

def get_module_name
(self.class.name =~ /^(.+::).+$/) ? $1 : ''
end

end

Assumptions:
1. Our object also contains nested objects. For example, we have an author who has articles, and each article has comments.
2. Names of our classes match the keys in our data.
3. All the classes of objects to be initialized have the same module name.
4. We want only attributes specified in the reader_attr to be present

Example of usage:

Module Blog
class Author
include InitFromHash
attr_reader :name, :article
end
end

module Blog
class Article
include InitFromHash
attr_reader :name, :abstract, :comment
end
end

module Blog
class Comment
include InitFromHash
attr_reader :text
end
end

When we receive out data in form:

data = {"author" => 'Mike', "article" => [{"name" => "Is there life on Mars",
"abstract" => "Probably", "comment" => [{"text" => "Really?"},
{"text" => "No way!"}]}, {"name" => "Milk is good for you",
"abstract" => "Scientists discovered", "comment" => [{"text" => "Really?"},
{"text" => "No way!"}] }}

Then we can initialize our instance as simple as

author = Author.new(data)
Advertisements

About RailsBlogger

I'm a Software Developer with over 10 years of experience, Java and Ruby on Rails.

Discussion

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: