YAML problem with serializing of nested object structures

K

Kjetil Orbekk

Hi!

I'm making a graph tool, and i have some problem with the
serialization of my graphs. The problem comes when i try to load a
graph i earlier serialized with YAML. In the objects i serialize, I
have two instance variables (arrays, as below) that contain some other
objects of similar type (also serialized). I managed to reproduce the
problem with a simpler object structure below. To me, this seems very
wierd, especially since it saves some data and breaks it when
loading. Could it be a bug, or am I doing something wrong here?

ruby --version is "1.8.4 (2005-12-24) [i486-linux]". My operating
system is Debian GNU/Linux 4.0.

Ruby code:
----------

require "yaml"

# Test class with two instance variables to hold arrays with similar
# objects
class Test
attr_accessor :c1, :c2
def initialize(c1=[], c2=[]) @c1, @c2 = c1, c2 end
end

a = Test.new
b = Test.new([a],[Test.new])
a.c1 << b
a.c2 << b

# The problem comes when saving the whole thing as an array
ary = [a, b]

yaml1 = YAML.dump(ary)

# +ary_from_yaml[0]+ looses its c2 even though it's clearly in the YAML output
ary_from_yaml = YAML.load(yaml1)

yaml2 = YAML.dump(ary_from_yaml)

print "YAML 1\n" + yaml1 + "\n\n"
print "YAML 2\n" + yaml2 + "\n\n"

print "YAML 1 length: #{yaml1.length} \tYAML 2 length: #{yaml2.length}"
 
D

dblack

Hi --

Hi!

I'm making a graph tool, and i have some problem with the
serialization of my graphs. The problem comes when i try to load a
graph i earlier serialized with YAML. In the objects i serialize, I
have two instance variables (arrays, as below) that contain some other
objects of similar type (also serialized). I managed to reproduce the
problem with a simpler object structure below. To me, this seems very
wierd, especially since it saves some data and breaks it when
loading. Could it be a bug, or am I doing something wrong here?

ruby --version is "1.8.4 (2005-12-24) [i486-linux]". My operating
system is Debian GNU/Linux 4.0.

Ruby code:
----------

require "yaml"

# Test class with two instance variables to hold arrays with similar
# objects
class Test
attr_accessor :c1, :c2
def initialize(c1=[], c2=[]) @c1, @c2 = c1, c2 end
end

a = Test.new
b = Test.new([a],[Test.new])
a.c1 << b
a.c2 << b

# The problem comes when saving the whole thing as an array
ary = [a, b]

yaml1 = YAML.dump(ary)

# +ary_from_yaml[0]+ looses its c2 even though it's clearly in the YAML output
ary_from_yaml = YAML.load(yaml1)

yaml2 = YAML.dump(ary_from_yaml)

print "YAML 1\n" + yaml1 + "\n\n"
print "YAML 2\n" + yaml2 + "\n\n"

print "YAML 1 length: #{yaml1.length} \tYAML 2 length: #{yaml2.length}"

I'm not totally sure but maybe the recursion is causing the problem.
You've got b containing a, and a's attributes containing b. I'm not
sure how YAML handles that kind of recursion.


David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
R

Robert Klemme

Hi!

I'm making a graph tool, and i have some problem with the
serialization of my graphs. The problem comes when i try to load a
graph i earlier serialized with YAML. In the objects i serialize, I
have two instance variables (arrays, as below) that contain some other
objects of similar type (also serialized). I managed to reproduce the
problem with a simpler object structure below. To me, this seems very
wierd, especially since it saves some data and breaks it when
loading. Could it be a bug, or am I doing something wrong here?

ruby --version is "1.8.4 (2005-12-24) [i486-linux]". My operating
system is Debian GNU/Linux 4.0.

First of all, there does not seem to be an issue with general recursive
structures:

$ irb -r yaml
irb(main):001:0> a=[1]
=> [1]
irb(main):002:0> b=[2,a]
=> [2, [1]]
irb(main):003:0> a << b
=> [1, [2, [...]]]
irb(main):004:0> b
=> [2, [1, [...]]]
irb(main):005:0> str = a.to_yaml
=> "--- &id001 \n- 1\n- - 2\n - *id001\n"
irb(main):007:0> c = YAML.load str
=> [1, [2, [...]]]
irb(main):008:0> c[1]
=> [2, [1, [...]]]

I changed your code a bit (attached) but with no new results. It seems,
you actually hit a bug in YAML. Marshal does not seem to have this
problem (see last output). So, if the output needs not be readable then
this is definitively an alternative - and it's also faster IIRC.

Kind regards

robert

require "yaml"
require 'pp'

# Test class with two instance variables to hold arrays with similar
# objects
class Test
attr_accessor :c1, :c2
def initialize(c1=[], c2=[]) @c1, @c2 = c1, c2 end
end

a = Test.new
b = Test.new([a],[Test.new])
a.c1 << b
a.c2 << b

# The problem comes when saving the whole thing as an array
ary = [a, b]
puts "Original:"
pp ary
puts ""

yaml1 = YAML.dump(ary)

# +ary_from_yaml[0]+ looses its c2 even though it's clearly in the YAML output
ary_from_yaml = YAML.load(yaml1)
puts "Copy:"
pp ary_from_yaml
puts ""

yaml2 = YAML.dump(ary_from_yaml)

print "YAML 1\n" + yaml1 + "\n\n"
print "YAML 2\n" + yaml2 + "\n\n"

p "YAML1", yaml1
p "YAML2", yaml2

print "YAML 1 length: #{yaml1.length} \tYAML 2 length: #{yaml2.length}\n"

pp Marshal.load(Marshal.dump(ary))
 

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,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top