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