Searched for tag YAML and found 3 results in 0.7 ms

Perl: Basic YAML parsing in a copy/pasteable function

I need very basic YAML parsing in Perl, mostly for reading configuration files. There aren't any great options in Perl core, and I only need a subset of YAML (basic scalars, arrays, and hashes), so I worked up a simple copy/pasteable function.

my $x = yaml_parse($yaml_str);

This implementation supports: nesting, scalars, arrays, and hashes, but is missing null / ~, booleans, and complex quotes.

sub yaml_parse {
    return {} unless defined $_[0] && length $_[0];
    my %data; my $root = \%data; my @st = ([-1, \$root]);
    for my $line (split /\n/, $_[0]) {
        $line =~ s/\r$//;
        next if $line =~ /^\s*(?:$|---\s*$|#)/;
        if ($line =~ /^(\s*)-\s*(.*)$/) {
            my ($n, $v) = (length($1), $2);
            pop @st while $n < $st[-1][0]; my $cur = ${$st[-1][1]};
            die "yaml_parse: array without parent: $line" if @st == 1;
            $cur = ${$st[-1][1]} = [] if ref $cur eq 'HASH' && !%$cur;
            die "yaml_parse: mixed array/hash" if ref $cur ne 'ARRAY';
            $v =~ s/^\s+|\s+$//g; $v =~ s/^(['"])(.*)\1$/$2/s;
            $v += 0 if $v =~ /^-?\d+(?:\.\d+)?$/; if ($v =~ /^([\w\-\.\/]+):\s*$/) {
            push(@$cur, my $el = {$1 => {}}); push(@st, [$n + 2, \$el->{$1}]); next; }
            push(@$cur, $v);
        } elsif ($line =~ /^(\s*)([\w\-\.\/]+)\s*:\s*(.*)$/) {
            my ($n, $key, $v) = (length($1), $2, $3);
            pop @st while $n <= $st[-1][0]; my $cur = ${$st[-1][1]};
            die "yaml_parse: '$key' under array" if ref $cur eq 'ARRAY';
            $v =~ s/\s+$//; $v =~ s/^\s+//; $v =~ s/^(['"])(.*)\1$/$2/s;
            if ($v =~ /^\[(.*)\]$/) {
                my @a = grep { length } map { s/^\s+|\s+$//gr =~ s/^(['"])(.*)\1$/$2/sr } split /,/, $1;
                for (@a) { $_ += 0 if /^-?\d+(?:\.\d+)?$/ } $v = \@a;
            } else { $v += 0 if $v =~ /^-?\d+(?:\.\d+)?$/; }
            if (ref $v or length $v) { $cur->{$key} = $v }
            else { $cur->{$key} = {}; push(@st, [$n, \$cur->{$key}]) }
        } else { warn "yaml_parse: ignoring: $line\n" }
    } return \%data;
}

YAML::XS is definitely the best Perl YAML parser, but it can be overkill if all you need is simple parsing.

Update: I wrote some unit tests to go along with this.

Tags:
Leave A Reply

YAML is growing on me

The more I learn about YAML, the more I like it. JSON is great as a machine readable format, but it sucks at being human readable. Want to add an element, better make sure you have all the commas and curly braces in the exact right place or the whole thing will be unusable. YAML on the other hand is designed to be human readable and modifiable. It's a very simple key/value system using indentation to represent layers.

PHP has a PECL module with good YAML support. There are also pure PHP versions if you're unable to install PECL modules. Symfony provides one, and so does Spyc. I prefer the latter because it's a single file and very easy to install.

On the Perl side there is YAML::XS, YAML::PP, and many others.

Parsing YAML is very easy in just about every language I can find. If you have a complex data structure that you need humans to interact with use YAML please.

Here is a great breakdown of when to use YAML vs JSON:

Use Case Recommended Why
API request/response JSON Universal support, strict parsing
Configuration files YAML Comments, readability
Browser/JavaScript JSON Native parsing
Kubernetes/Docker YAML Industry standard
Data interchange JSON Unambiguous, fast
Human-edited files YAML Less punctuation

YAML spec differences.

Tags:
Leave A Reply

Comparison of markup languages

I've been investigating JSON vs YAML vs TOML for various applications. After testing many variations I ended up writing a simple tool to compare all three live.

Tags:
Leave A Reply