YAML and hash

A

Artur Merke

Hi,

is there a possibility to recognize multiple keys while
reading a hash using YAML?

example:

arr= YAML::load("aaa: 1\nbbb: 2\naaa: 3" )
=> {"aaa"=>3, "bbb"=>2}

but I would like to get a warning or an exception when
encountering the key 'aaa' for the second time, and not just
get the first entry overwritten.

Any ideas?
 
R

Robert Klemme

Artur Merke said:
Hi,

is there a possibility to recognize multiple keys while
reading a hash using YAML?

example:

arr= YAML::load("aaa: 1\nbbb: 2\naaa: 3" )
=> {"aaa"=>3, "bbb"=>2}

but I would like to get a warning or an exception when
encountering the key 'aaa' for the second time, and not just
get the first entry overwritten.

Any ideas?

I don't have much insight into YAML internals but you'll probably be able
to do that with YAML#add_builtin_type or YAML#add_ruby_type
http://www.ruby-doc.org/core/classes/YAML.html#M001712

Kind regards

robert
 
N

Navindra Umanee

Robert Klemme said:
I don't have much insight into YAML internals but you'll probably be able
to do that with YAML#add_builtin_type or YAML#add_ruby_type
http://www.ruby-doc.org/core/classes/YAML.html#M001712

I would hazard a guess that YAML is deferring to the Hash constructor
to create hashes. The Ruby Hash behaves the same way:

irb(main):017:0> {1=>2, 1=>3}
=> {1=>3}

I had the idea that by changing the behaviour of Hash, the behaviour
of YAML would automatically change. Unfortunately, re-defining
Hash.store does not seem to be enough.

Hash is implemented in C and all Hash creations/stores are handled by
rb_hash_aset. I can't figure how to redefine this in Ruby.

Cheers,
Navin.
 
R

Robert Klemme

Navindra Umanee said:
I would hazard a guess that YAML is deferring to the Hash constructor
to create hashes. The Ruby Hash behaves the same way:

irb(main):017:0> {1=>2, 1=>3}
=> {1=>3}

I had the idea that by changing the behaviour of Hash, the behaviour
of YAML would automatically change. Unfortunately, re-defining
Hash.store does not seem to be enough.

Hash is implemented in C and all Hash creations/stores are handled by
rb_hash_aset. I can't figure how to redefine this in Ruby.

That's why you have to work with YAML IMHO.

robert
 
W

why the lucky stiff

Artur said:
Hi,

is there a possibility to recognize multiple keys while
reading a hash using YAML?

example:

arr= YAML::load("aaa: 1\nbbb: 2\naaa: 3" )
=> {"aaa"=>3, "bbb"=>2}

but I would like to get a warning or an exception when
encountering the key 'aaa' for the second time, and not just
get the first entry overwritten.
You're right. This should throw an error or a warning (according the
YAML specification). This a simple fix, but cannot be done in Ruby.

I've added this to the bug tracker on RubyForge. Thankyou!

_why
 
A

Adriano Ferreira

You're right. This should throw an error or a warning (according the
YAML specification). This a simple fix, but cannot be done in Ruby.

I've spent some time trying to write code to make such a thing work.
I've just found that I don't know nothing about Ruby.

I wrote the following Hash subclass that I thought could be forced
into the YAML parser (maybe through a simple explicit header like '---
!ruby/hash:AngryHash' or via a directive to the YAML parser locally
use AngryHash'es rather than primitive Hash'es).

class AngryHash < Hash

def []=(key, value)
if has_key?(key)
raise "not again: duplicate key '" + key.to_s + "'"
end
super(key, value)
end

def AngryHash.[](pairs)
h = new
pairs.each_pair {|k,v| h[k] = v}
h
end

end

Well, the rationale is not to allow pairs which keys that already
appeared (AngryHash#[]= in a pair-by-pair basis) and I guessed that
something like Hash[k1 => v1, ... ] is used by YAML parser when
constructing map-like objects. This is a dead-end. If the parser uses
this form, pairs with repeated keys were already trashed (except for
the last one) and this code is good for nothing.

The fix why_ mentioned has to do with this behaviour? If I tried to
subclass YAML::pairs, would it work?

Regards,
Adriano.
 

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

No members online now.

Forum statistics

Threads
474,169
Messages
2,570,918
Members
47,458
Latest member
Chris#

Latest Threads

Top