how to add YAML serialization support to a class?

L

Luca Pireddu

Hello. Can someone point me to some documentation describing how to add YAML
support to a class? I have a class that contains an RGL graph. I'd like to
be able to save it and restore it, but

YAML::dump(RGL::DirectedAdjacencyGraph.new)

throws an exception

TypeError: can't dump anonymous class Class
from /usr//lib/ruby/1.8/yaml/rubytypes.rb:9:in `to_yaml'
from /usr//lib/ruby/1.8/yaml/baseemitter.rb:181:in `map'
from /usr//lib/ruby/1.8/yaml/baseemitter.rb:170:in `each'
from /usr//lib/ruby/1.8/yaml/baseemitter.rb:170:in `map'
from /usr//lib/ruby/1.8/yaml/rubytypes.rb:25:in `to_yaml'
from /usr//lib/ruby/1.8/yaml/rubytypes.rb:24:in `call'
from /usr//lib/ruby/1.8/yaml.rb:373:in `quick_emit'
from /usr//lib/ruby/1.8/yaml/rubytypes.rb:24:in `to_yaml'
from /usr//lib/ruby/1.8/yaml.rb:103:in `dump'

TIA.

Luca
 
J

Joel VanderWerf

Luca said:
Hello. Can someone point me to some documentation describing how to add YAML
support to a class? I have a class that contains an RGL graph. I'd like to
be able to save it and restore it, but

YAML::dump(RGL::DirectedAdjacencyGraph.new)

throws an exception

TypeError: can't dump anonymous class Class

Looks like the problem is that somewhere in the graph of objects
connected to your instance is a Class object:

$ irb -r yaml
irb(main):001:0> YAML.dump(Class)
TypeError: can't dump anonymous class Class
...

(I don't see what's anonymous about Class...)

Anyway, there's nothing shameful about wanting to yaml a class! It's
easy to convince YAML to let you do it:

require 'yaml'

class Module
def is_complex_yaml?
false
end
def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out|
out << "!ruby/module "
self.name.to_yaml( :Emitter => out )
}
end
end
YAML.add_ruby_type(/^module/) do |type, val|
subtype, subclass = YAML.read_type_class(type, Module)
val.split(/::/).inject(Object) { |p, n| p.const_get(n)}
end

class Class
def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out|
out << "!ruby/class "
self.name.to_yaml( :Emitter => out )
}
end
end
YAML.add_ruby_type(/^class/) do |type, val|
subtype, subclass = YAML.read_type_class(type, Class)
val.split(/::/).inject(Object) { |p, n| p.const_get(n)}
end

p YAML.dump(Class) # ==> "--- !ruby/class Class"


So, really, all that is getting written is a reference to the class. Any
state in the class itself (class vars, class instance vars) is not stored.
 
L

Luca Pireddu

Joel said:
Looks like the problem is that somewhere in the graph of objects
connected to your instance is a Class object:

$ irb -r yaml
irb(main):001:0> YAML.dump(Class)
TypeError: can't dump anonymous class Class
..

(I don't see what's anonymous about Class...)

Anyway, there's nothing shameful about wanting to yaml a class! It's
easy to convince YAML to let you do it:

require 'yaml'

class Module
def is_complex_yaml?
false
end
def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out|
out << "!ruby/module "
self.name.to_yaml( :Emitter => out )
}
end
end
YAML.add_ruby_type(/^module/) do |type, val|
subtype, subclass = YAML.read_type_class(type, Module)
val.split(/::/).inject(Object) { |p, n| p.const_get(n)}
end

class Class
def to_yaml( opts = {} )
YAML::quick_emit( nil, opts ) { |out|
out << "!ruby/class "
self.name.to_yaml( :Emitter => out )
}
end
end
YAML.add_ruby_type(/^class/) do |type, val|
subtype, subclass = YAML.read_type_class(type, Class)
val.split(/::/).inject(Object) { |p, n| p.const_get(n)}
end

p YAML.dump(Class) # ==> "--- !ruby/class Class"


So, really, all that is getting written is a reference to the class. Any
state in the class itself (class vars, class instance vars) is not stored.

Thanks for your reply Joel. I think I understand the basic idea. To emit,
define a method #to_yaml in your class. To enable YAML to load your class
register the type with YAML using one of the add_x_type methods, and
associate a block that knows how to recreate your data structure from the
YAML parse tree.

For anyone who may be interested, I've found helpful documentation at this
site:
http://yaml4r.sourceforge.net/doc/

Luca
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,231
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top