Validating YAML with Ruby

YAML is a pretty common data serialization language. When compared to other serialization languages like JSON, YAML does offer more features and flexibility. Unfortunately this also makes it easier to make mistakes with YAML.

Validating files

Below is a trivial YAML file:

---
key:
  - foo
  - bar

At first glance the file looks fine, however first item is indented with a tab. As a result the file doesn't meet the YAML spec:

$ hexdump -c example.yaml
0000000   -   -   -  \n   k   e   y   :  \n  \t   -       f   o   o  \n
0000010           -       b   a   r  \n
0000018

The following Ruby command can be used to check for errors in the file:

ruby -r yaml -e 'YAML.load_file ARGV[0];puts "ok"' example.yaml

This command uses the Ruby YAML library, loaded by -r, to try to parse the file specified by the first argument. Running this should produce a stack trace similar to the following for the example above:

/usr/share/ruby/psych.rb:205:in `parse': (example.yaml): found character that cannot start any token while scanning for the next token at line 3 column 1 (Psych::SyntaxError)
        from /usr/share/ruby/psych.rb:205:in `parse_stream'
        from /usr/share/ruby/psych.rb:153:in `parse'
        from /usr/share/ruby/psych.rb:129:in `load'
        from /usr/share/ruby/psych.rb:299:in `block in load_file'
        from /usr/share/ruby/psych.rb:299:in `open'
        from /usr/share/ruby/psych.rb:299:in `load_file'
        from -e:1:in `<main>'

The example above can quickly be fixed by using sed to replace leading tabs with spaces:

$ sed -i 's/^\t/  /' example.yaml

Once the YAML file has been fixed, running the command again should return ok:

$ ruby -r yaml -e 'YAML.load_file ARGV[0];puts "ok"' example.yaml
ok

Reading from stdin

Alternatively the command above can be adapted to read from STDIN instead:

ruby -r yaml -e 'YAML.load STDIN;puts "ok"'

This is useful if the YAML is being generated from another command. For example:

$ curl -s http://localhost:8000/example | ruby -r yaml -e 'YAML.load STDIN;puts "ok"'
ok

Validating JSON

The Ruby JSON library can be used in a similar way to validate JSON files:

$ ruby -r json -e 'JSON.load File.open(ARGV[0]);puts "ok"' example.json
ok

And to validate JSON from STDIN:

$ cat example.json | ruby -r json -e 'JSON.load STDIN;puts "ok"'
ok