ActiveRecord from_json and from_xml

Unless I’m missing something, the default rails from_json and from_xml methods don’t work with data that have associated objects. Here are routines that work for some simple examples I’ve tested. I placed this code in vendor/rails/activerecord/lib/active_record/base.rb within the ActiveRecord::Base class, but there might be a better place to put it.

def self.from_hash( hash )
  h = hash.dup
  h.each do |key,value| 
    case value.class.to_s
    when 'Array'
      h[key].map! { |e|
         Object.const_get(key.camelize.singularize).from_hash e }
    when 'Hash'
      h[key] = Object.const_get(key.camelize).from_hash value
    end 
  end     
  self.new h
end   
 
def self.from_json( json )
  hash = ActiveSupport::JSON.decode json
  self.from_hash hash
end   
 
# The xml has a surrounding class tag (e.g. ship-to),
# but the hash has no counterpart (e.g. 'ship_to' => {} )
def self.from_xml( xml )
  hash = Hash.from_xml xml
  self.from_hash hash[self.to_s.underscore]
end

Also available on pastie.

Example usage, using the to_xml example:

xml = firm.to_xml :include => [ :account, :clients ]
firm = Firm.from_xml xml

Note: this only works if the classes of the nested objects are canonically named. If any of your associations use the :class_name option, you will probably need to update this code to discover the proper class names.

I just wrote this a couple hours ago, so please consider this to be an alpha version.

Share:
  • del.icio.us
  • Reddit
  • Technorati
  • Twitter
  • Facebook
  • Google Bookmarks
  • HackerNews
  • PDF
  • RSS
This entry was posted in programming, rails and tagged , , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

3 Comments

  1. Posted August 11, 2008 at 2:08 pm | Permalink

    Thanks Matt. It was nice to find that i wasn’t alone w/ the weird from_xml behavior. ‘Preciate the sample code too.

  2. Posted August 11, 2008 at 6:36 pm | Permalink

    I knew I wasn’t the only one. :) I’ve since generalized the code and tested it more thoroughly. The upgrade is here.

    If anyone finds any bugs, send me a simple test case and I will try to fix it.

  3. Posted September 2, 2009 at 12:43 pm | Permalink

    If you need to de-serialize from XML that contains an array of objects you can also use this: http://gist.github.com/179530

One Trackback

  1. By ActiveRecord from_xml (and from_json) part 2 on August 11, 2008 at 6:33 pm

    [...] post is an upgrade to the previous post about the unmarshalling of XML and JSON strings into rails objects, with arbitrarily deep object [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">