Ruby JSON

Working with JSON data in Ruby applications

📊 What is JSON?

JSON (JavaScript Object Notation) is a lightweight data format for storing and exchanging data. Ruby's JSON library makes it easy to parse and generate JSON for APIs and data storage.


require 'json'

# Convert Ruby hash to JSON
data = { name: "Alice", age: 25 }
json_string = JSON.generate(data)
puts json_string
                                    

Output:

{"name":"Alice","age":25}

Key JSON Operations

📥

Parse JSON

Convert JSON to Ruby objects

data = JSON.parse(json_string)
puts data["name"]
📤

Generate JSON

Convert Ruby to JSON

json = JSON.generate(hash)
json = hash.to_json
📁

File Operations

Read/write JSON files

File.write("data.json", json)
JSON.parse(File.read("data.json"))
🎨

Pretty Print

Format JSON nicely

JSON.pretty_generate(data)

🔹 Parsing JSON

Convert JSON strings into Ruby hashes and arrays using JSON.parse. This is essential when receiving data from APIs, reading configuration files, or processing JSON from external sources.

require 'json'

# Parse simple JSON object
json_string = '{"name":"Bob","age":30,"city":"New York"}'
person = JSON.parse(json_string)

puts "Name: #{person["name"]}"
puts "Age: #{person["age"]}"
puts "City: #{person["city"]}"

# Parse JSON array
json_array = '[{"id":1,"title":"First"},{"id":2,"title":"Second"}]'
items = JSON.parse(json_array)

items.each do |item|
  puts "ID: #{item["id"]}, Title: #{item["title"]}"
end

# Parse nested JSON
nested_json = '{"user":{"name":"Charlie","address":{"city":"Boston","zip":"02101"}}}'
data = JSON.parse(nested_json)

puts "User: #{data["user"]["name"]}"
puts "City: #{data["user"]["address"]["city"]}"

Output:

Name: Bob
Age: 30
City: New York
ID: 1, Title: First
ID: 2, Title: Second
User: Charlie
City: Boston

🔹 Generating JSON

Convert Ruby objects (hashes, arrays, and custom objects) into JSON strings. Use JSON.generate or the to_json method to create JSON for APIs, file storage, or data transmission.

require 'json'

# Convert hash to JSON
user = {
  name: "Diana",
  email: "[email protected]",
  age: 28,
  active: true
}

json = JSON.generate(user)
puts json

# Alternative syntax
json2 = user.to_json
puts json2

# Convert array to JSON
users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
  { id: 3, name: "Charlie" }
]

json_array = JSON.generate(users)
puts json_array

# Convert nested structures
company = {
  name: "TechCorp",
  employees: [
    { name: "John", role: "Developer" },
    { name: "Jane", role: "Designer" }
  ],
  location: { city: "Seattle", country: "USA" }
}

puts JSON.generate(company)

Output:

{"name":"Diana","email":"[email protected]","age":28,"active":true}
{"name":"Diana","email":"[email protected]","age":28,"active":true}
[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"},{"id":3,"name":"Charlie"}]
{"name":"TechCorp","employees":[{"name":"John","role":"Developer"},{"name":"Jane","role":"Designer"}],"location":{"city":"Seattle","country":"USA"}}

🔹 Pretty Printing JSON

Format JSON with proper indentation and line breaks for better readability. This is especially useful for debugging, logging, or creating human-readable configuration files that need to be edited manually.

require 'json'

data = {
  company: "TechStart",
  founded: 2020,
  products: ["App", "Web", "API"],
  team: {
    developers: 5,
    designers: 2,
    managers: 1
  }
}

# Pretty print with default indentation
pretty_json = JSON.pretty_generate(data)
puts pretty_json

puts "\n--- Custom Indentation ---\n"

# Pretty print with custom options
custom_json = JSON.pretty_generate(data, indent: "  ", space: " ", object_nl: "\n")
puts custom_json

# Write pretty JSON to file
File.write("config.json", pretty_json)
puts "\nPretty JSON saved to config.json"

Output:

{
  "company": "TechStart",
  "founded": 2020,
  "products": [
    "App",
    "Web",
    "API"
  ],
  "team": {
    "developers": 5,
    "designers": 2,
    "managers": 1
  }
}

Pretty JSON saved to config.json

🔹 Reading and Writing JSON Files

Store and retrieve data from JSON files for configuration, data persistence, or data exchange. This is a common pattern for saving application settings, user preferences, or cached data between program runs.

require 'json'

# Write JSON to file
users = [
  { id: 1, name: "Alice", email: "[email protected]" },
  { id: 2, name: "Bob", email: "[email protected]" },
  { id: 3, name: "Charlie", email: "[email protected]" }
]

File.write("users.json", JSON.pretty_generate(users))
puts "Data written to users.json"

# Read JSON from file
if File.exist?("users.json")
  json_data = File.read("users.json")
  loaded_users = JSON.parse(json_data)
  
  puts "\nLoaded users:"
  loaded_users.each do |user|
    puts "  #{user["id"]}: #{user["name"]} (#{user["email"]})"
  end
end

# Update JSON file
loaded_users << { id: 4, name: "Diana", email: "[email protected]" }
File.write("users.json", JSON.pretty_generate(loaded_users))
puts "\nUser added and file updated"

Output:

Data written to users.json

Loaded users:
  1: Alice ([email protected])
  2: Bob ([email protected])
  3: Charlie ([email protected])

User added and file updated

🔹 Working with Symbols

By default, JSON.parse creates hashes with string keys. Use the symbolize_names option to convert keys to symbols, which is more idiomatic in Ruby and allows cleaner syntax with symbol access.

require 'json'

json_string = '{"name":"Eve","age":32,"role":"admin"}'

# Parse with string keys (default)
data_strings = JSON.parse(json_string)
puts "With strings: #{data_strings["name"]}"

# Parse with symbol keys
data_symbols = JSON.parse(json_string, symbolize_names: true)
puts "With symbols: #{data_symbols[:name]}"

# Accessing nested data with symbols
nested_json = '{"user":{"profile":{"name":"Frank","level":5}}}'
nested = JSON.parse(nested_json, symbolize_names: true)

puts "Nested access: #{nested[:user][:profile][:name]}"
puts "Level: #{nested[:user][:profile][:level]}"

# Generate JSON from hash with symbols
person = { name: "Grace", age: 29, city: "Portland" }
json_output = JSON.generate(person)
puts "\nGenerated: #{json_output}"

Output:

With strings: Eve
With symbols: Eve
Nested access: Frank
Level: 5

Generated: {"name":"Grace","age":29,"city":"Portland"}

🧠 Test Your Knowledge

Which method converts a Ruby hash to JSON?