ActiveRecord from_json and from_xml

(Edited 2 Sept 2011: Please see instead the updated post here: ActiveRecord from_xml (and from_json) part 2.)

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 rails and tagged , , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
  • http://blog.petemckinstry.com Pete McKinstry

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

  • http://www.xcombinator.com/2008/08/11/activerecord-from_xml-and-from_json-part-2/ ActiveRecord from_xml (and from_json) part 2

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

  • http://quantumlab.net Matt Pulver

    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.

  • http://simonwoodside.com S Woodside

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

  • http://bandaidprogramming.blogspot.com Terence

    Dude, you are the bomb. Thanks for your fix. Helped us out heaps.