Deserialize Objects From YAML

February 15, 2007

Coding in Ruby is like using a Mac. If you’re not used to it, you spend quite some time looking for an obtuse way to do something, only to come to a “one line of code” solution about 2 hours later.

For me, I wanted to deserialize a YAML serialized ActiveRecord::Base subclass. Looking at the YAMLrdoc, it appeared that I could register a custom type via YAML::add_domain_type – but I wanted to Google around a bit just to see if anyone had already solved this <ahem>YAML deserialization problem</ahem>, to find me some sample code.

I learned nothing via Google, so I turned to the handy rails console (may it live forever) for a quick test, and I ended up with something like this:

monkey:~/Work/[client]/trunk daniel$ ruby script/console
Loading development_daniel environment.
>>
>> class BlaTest
>> attr_accessor :bla
>> end
=> nil
>> b = BlaTest.new
=> #<BlaTest:0x3718164>
>> b.bla = "Yay Test"
=> "Yay Test"
>> c = YAML::load( b.to_yaml )
=> #<BlaTest:0x37138bc @bla="Yay Test">
>> c.class
=> BlaTest
>> c.bla
=> "Yay Test"

So basically, we’ve created a new class with a single property, instantiated an instance of the class, set the property, and then we’ve called YAML::load for the YAML representation of our created instance. The result of YAML::load we’ve assigned to c.

To my surprise (astonishment?), I didn’t even need to register my custom type at all. As you can see, the resulting instance c is of type BlaClass with the appropriate value for the bla property.

One line of code. Beautiful.

Comments

There are 2 comments on this post. Post yours →

Thanks for sharing Daniel, yeah I love YAML, the best part you can easily store this in database text field and retrieve it later on, comes in pretty handy in many occasions. :)

Came across your post in roughly the same quest. Thanks for posting it!

One gotcha: for deserialized objects coming out of YAML::load of the YAML::Object class (the rdoc says these are unresolved objects, so I assume this is for objects that YAML can’t “typecast” into the right class, or perhaps that have no defined mapping, and this is true of AR objects), yaml_object.class is actually a String since there is an instance variable @class that overrides what you’d expect to return you the class. This bit of code should resolve it to the correct class:

klass = class_name.split(’::’).inject(Object) { |klass,part| klass.const_get(part) }

Post a comment

Required fields in bold.