Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserve YAML order perl

Tags:

module

yaml

perl

I want to read data from a YAML file but I need the order of the elements to be preserved.
Is there a module in perl which has this functionality and how to do that?


In response to @mugen kenichi

I managed to do what I want but I don't believe that this is a reasonable solution.

old YAML:

foo:
   bar: some value
   baz: other value
qwe:
   bar: yet another value
   baz: again

new YAML

 -
   foo:
      bar: some value
      baz: other value
 -  
   qwe:
      bar: yet another value
      baz: again
like image 682
bliof Avatar asked Aug 24 '11 07:08

bliof


2 Answers

UPDATE: YAML.pm now supports order preservation. See this up-to-date answer.

The YAML spec specifically states that "mapping keys do not have an order" and that "in every case where node order is significant, a sequence must be used". To infer order from a mapping would be in violation of the spec. Using ordered mappings, as mentioned by mugen, is the correct solution to preserve order.

If you *really* wanted to, you could somehow get a YAML parser to dump into a [Tie::IxHash][2] which will preserve order... but I know of no Perl YAML parser which gives you that level of control. It's possible you could do something with [YAML::Old::Loader][3], but that is not a very good YAML parser and YAML::Old::Loader is not documented.

A third option would be to use explicit YAML tags (aka types) to instruct the parser to load your mappings as a special type and then you supply the callback... but even then it's likely the YAML parser will supply your callback with an unordered hash.

I would suggest you simply change the YAML. The point of a portable data language is that all the semantic meaning is explicit in the data file or the spec, not implicit in a particular parser. Ordered mappings are an accepted, compact YAML idiom.

- foo:
      bar: some value
      baz: other value
- qwe:
      bar: yet another value
      baz: again
like image 89
Schwern Avatar answered Oct 04 '22 21:10

Schwern


It is possible with YAML::PP since version 0.021.

use YAML::PP;
use YAML::PP::Common qw/ :PRESERVE /;
my $yp = YAML::PP->new( preserve => PRESERVE_ORDER );
my $data = $yp->load-string($yaml);
say $yp->dump_string($data);

(Disclaimer: I'm the module's author)

like image 44
tinita Avatar answered Oct 04 '22 22:10

tinita