YPS: YAML Positioning System
YPS is a gem to parse YAML and add position information (file name, line and column) to each parsed elements. This is useful for error reporting and debugging, allowing developers to precisely locate an issue within the original YAML file.
Installation
Install the gem and add to the application's Gemfile by executing:
bundle add yps
If bundler is not being used to manage dependencies, install the gem by executing:
gem install yps
Usage
You can use the methods below to load a YAML code into Ruby objects with their position information (file name, line, and column).
YPS.safe_loadYPS.loadYPS.safe_load_streamYPS.load_stream- Load the given YAML string into Ruby objects with position information.
YPS.safe_load_fileYPS.load_fileYPS.safe_load_stream_fileYPS.load_stream_file- Load the YAML code read from the given file path into Ruby objects with position information.
For a YAML code that contains multiple documents, following methods load the 1st document only.
YPS.safe_loadYPS.loadYPS.safe_load_fileYPS.load_file
On the other hand, following methods load all given documents and return them as a list.
YPS.safe_load_streamYPS.load_streamYPS.safe_load_stream_fileYPS.load_stream_file
Parsed objects, except for hash keys, have their own position information.
You can use the position method to get position information in the original YAML of the receiver object.
require 'yps'
yaml = YPS.load(<<~'YAML')
children:
- name: kanta
age: 8
- name: kaede
age: 3
YAML
# output
# name: kanta (filename: unknown line 2 column 11)
# age: 8 (filename: unknown line 3 column 10)
# name: kaede (filename: unknown line 4 column 11)
# age: 3 (filename: unknown line 5 column 10)
yaml['children'].each do |child|
child.each do |key, value|
puts "#{key}: #{value} (#{value.position})"
end
end
yaml = YPS.load_stream(<<~'YAML')
- 0
- 1
---
- foo
- bar
YAML
# output
# 0 (filename: unknown line 1 column 3)
# 1 (filename: unknown line 2 column 3)
# foo (filename: unknown line 4 column 3)
# bar (filename: unknown line 5 column 3)
yaml.each do |list|
list.each do |item|
puts "#{item} (#{item.position})"
end
end
By default, all objects, including false and nil, are wrapped with the wrapper class.
This is important because wrapped false and nil objects no longer act as falsy values.
You can use the unwrapped_classes option to avoid this situation.
Objects belonging to classes specified by this option are returned unwrapped but will not have access to their position information.
yaml = YPS.load(<<~'YAML')
- false
- null
YAML
# output
# false
# nil
puts (yaml[0] || 'foo').inspect
puts (yaml[1] || 'bar').inspect
yaml = YPS.load(<<~'YAML', unwrapped_classes: [FalseClass, NilClass])
- false
- null
YAML
# output
# "foo"
# "bar"
puts (yaml[0] || 'foo').inspect
puts (yaml[1] || 'bar').inspect
For more details about these APIs, please visit here.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/taichi-ishitani/yps.
Copyright & License
Copyright © 2025 Taichi Ishitani. YPS is licensed under the terms of the MIT License, see LICENSE.txt for further details.
Code of Conduct
Everyone interacting in the YPS project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.