Working with JSON and YAML
Prerequisites: Hashes, Working with files
JSON is the most common format for sending data between programs — every web API speaks it. YAML is a more human-friendly format used for configuration files. Ruby's standard library handles both.
Ruby → JSON
require "json"
user = { name: "Ada", languages: ["Ruby", "C"], active: true, manager: nil }
puts user.to_json
puts JSON.pretty_generate(user)
{"name":"Ada","languages":["Ruby","C"],"active":true,"manager":null}
{
"name": "Ada",
"languages": [
"Ruby",
"C"
],
"active": true,
"manager": null
}
nil becomes null, and symbol keys become strings — JSON has no
symbols.
JSON → Ruby
require "json"
text = '{"name": "Ada", "age": 36, "tags": ["admin"]}'
data = JSON.parse(text)
p data["name"]
data = JSON.parse(text, symbolize_names: true)
p data[:age]
p data
"Ada"
36
{name: "Ada", age: 36, tags: ["admin"]}
By default, parsed keys are strings. symbolize_names: true turns
them into symbols, which matches Ruby style and works with pattern
matching.
Invalid JSON raises JSON::ParserError — rescue it whenever the text
comes from outside your program. The JSON Formatter
is handy for inspecting a payload that won't parse.
YAML
require "yaml"
config = YAML.safe_load(<<~YAML, symbolize_names: true)
app:
name: Shop
port: 3000
features:
- search
- checkout
YAML
p config[:app][:port]
p config[:features]
3000
["search", "checkout"]
Use YAML.safe_load (or YAML.load_file for files) for YAML you
didn't write yourself. It only builds plain data — hashes, arrays,
strings, numbers — and refuses to create arbitrary Ruby objects, which
could otherwise be a security hole.
Common mistakes
- Parsing JSON and reading
data[:name]—nil, because the keys are strings unless you passedsymbolize_names: true. - Using
YAML.unsafe_loadon untrusted input.