Question

How to Convert a Ruby Hash to JSON

rubyruby-on-railsjsonhashmap

Question

How can you convert a Ruby Hash object to JSON?

For example, why does the following code not work in some Ruby environments?

car = { :make => "bmw", :year => "2003" }
car.to_json

I noticed that Hash does not always appear to have a to_json method in plain Ruby documentation. However, many examples online show that Rails supports ActiveRecord#to_json and also Hash#to_json.

Since ActiveRecord is part of Rails but Hash is a core Ruby object, why can hash.to_json work in Rails but not always in plain Ruby?

Short Answer

By the end of this page, you will understand how JSON conversion works for Ruby hashes, why to_json may work automatically in Rails, and how to use the correct library in plain Ruby. You will also see the difference between to_json and JSON.generate, common mistakes, and practical examples.

Concept

JSON is a text format used to exchange structured data between programs. Ruby uses Hash objects to store key-value pairs, and JSON uses objects that look very similar.

For example:

{ name: "Alice", age: 30 }

becomes:

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

Although Ruby hashes and JSON objects look similar, they are not the same thing:

  • A Ruby Hash is an in-memory Ruby object.
  • JSON is a string.

That means converting a hash to JSON is really serialization: turning a Ruby object into a JSON-formatted string.

In plain Ruby, JSON support usually comes from the standard json library, which you must load first:

require 'json'

After that, Ruby can serialize hashes and other supported objects.

In Rails, many features are preloaded for you. Rails commonly adds or exposes methods like to_json in a way that feels automatic. That is why code may work in Rails without extra setup, but fail in a plain Ruby script unless you explicitly require the JSON library.

This matters in real programming because JSON is everywhere:

  • API responses
  • configuration data
  • background job payloads
  • logging and event data
  • communication between services

Mental Model

Think of a Ruby hash as a packed suitcase full of labeled items, and JSON as the shipping label format required by another system.

Inside your Ruby program, the suitcase can stay in Ruby form:

{ make: "bmw", year: "2003" }

But if you want to send that data to a browser, an API, or another service, you need to print it in the correct transport format:

{"make":"bmw","year":"2003"}

So to_json is like converting your suitcase contents into a standard label that other systems can read.

Take Quiz

Syntax and Examples

The most common way in plain Ruby is to require the JSON library and then call to_json or use JSON.generate.

Basic example

require 'json'

car = { make: 'bmw', year: '2003' }
puts car.to_json

Output:

{"make":"bmw","year":"2003"}

Using JSON.generate

require 'json'

car = { make: 'bmw', year: '2003' }
puts JSON.generate(car)

This produces the same result.

Nested hash example

require 'json'

car = {
  make: 'bmw',
  year: '2003',
  owner: {
    name: 'Sam',
    city: 'Boston'
  }
}

puts car.to_json

Output:

{"make":"bmw","year":"2003","owner":{"name":"Sam","city":"Boston"}}

Pretty JSON output

require 'json'

car = { make: 'bmw', year: '2003' }
puts JSON.pretty_generate(car)

Output:

{
  "make": "bmw",
  "year": "2003"
}

Why your original example fails sometimes

If you run this in plain Ruby without loading JSON support:

car = { :make => 'bmw', :year => '2003' }
car.to_json

you may get an error like:

NoMethodError: undefined method `to_json'

That happens because the JSON functionality has not been loaded yet.

Step by Step Execution

Consider this example:

require 'json'

car = { make: 'bmw', year: '2003' }
json_text = car.to_json
puts json_text

Here is what happens step by step:

  1. require 'json'

    • Ruby loads the JSON library.
    • This adds JSON serialization support.
  2. car = { make: 'bmw', year: '2003' }

    • A Ruby hash is created.
    • It has two keys: :make and :year.
  3. json_text = car.to_json

    • Ruby converts the hash into a JSON string.
    • The result is not a hash anymore.
    • It is now text:
    "{\"make\":\"bmw\",\"year\":\"2003\"}"
    
  4. puts json_text

    • Ruby prints the JSON string in readable form:
    {"make":"bmw","year":"2003"}
    

Important detail about keys

Ruby hash keys may be symbols:

{ make: 'bmw' }

But JSON object keys are always strings. So after conversion, the key becomes:

"make"

Real World Use Cases

Converting a hash to JSON is common in many kinds of Ruby programs.

API responses

A web app often builds a hash and returns it as JSON:

response = { status: 'ok', user_id: 42 }
puts response.to_json

Sending data to another service

If your Ruby app calls an external API, it may need to send JSON in the request body.

payload = { email: 'user@example.com', active: true }
json_body = payload.to_json

Saving structured logs

Applications sometimes store log entries as JSON for easier searching.

log_entry = { level: 'info', message: 'User signed in' }
puts log_entry.to_json

Background jobs and queues

Job payloads are often serialized before being stored or transmitted.

job = { type: 'send_email', user_id: 7 }
serialized = job.to_json

Config export

A script may convert internal data into JSON for another tool to consume.

Take Quiz

Real Codebase Usage

In real projects, developers often do more than call to_json directly.

Pattern: explicit serialization

In plain Ruby scripts, many developers prefer this:

require 'json'
JSON.generate(data)

Why:

  • it makes the JSON dependency obvious
  • it is clear that serialization is happening
  • it avoids confusion about whether to_json is available

Pattern: rendering JSON in Rails

In Rails controllers, developers usually return hashes as JSON through framework helpers:

render json: { status: 'ok', message: 'Saved' }

Rails handles serialization for you.

Pattern: building response hashes first

A common approach is:

  1. build a plain Ruby hash
  2. serialize it only at the boundary of the system
result = {
  user: user.name,
  admin: user.admin?
}

JSON.generate(result)

This keeps your internal logic Ruby-friendly.

Pattern: validation before serialization

Developers often validate or normalize data first:

data = { email: email, active: !!active }
raise 'Missing email' if data[:email].nil?

JSON.generate(data)

Pattern: pretty output for debugging

Pretty formatting is useful in scripts and debugging tools:

puts JSON.pretty_generate(config)

Common Mistakes

1. Forgetting to load the JSON library

Broken code:

car = { make: 'bmw', year: '2003' }
car.to_json

Problem:

  • In plain Ruby, to_json may not be available until you load JSON support.

Fix:

require 'json'
car = { make: 'bmw', year: '2003' }
car.to_json

2. Confusing a hash with a JSON string

Broken assumption:

car = { make: 'bmw' }
json_car = car.to_json
puts json_car[:make]

Problem:

  • json_car is a string, not a hash.
  • String indexing does not work like hash access.

Fix:

require 'json'
car = { make: 'bmw' }
json_car = car.to_json
puts json_car

If you need a hash again, parse the JSON.

3. Typo in variable names

Your original example used both Copycar and car, which are different names.

Broken code:

Copycar = { :make => 'bmw', :year => '2003' }
car.to_json

Problem:

  • Copycar and car are not the same variable.
  • Copycar starts with a capital letter, which Ruby treats as a constant name.

Fix:

require 'json'
car = { make: 'bmw', year: '2003' }
car.to_json

4. Assuming Rails behavior is the same as plain Ruby

Problem:

  • Rails loads many helpful features automatically.
  • A standalone Ruby script does not always do that.

Avoid this by testing code in the actual environment where it will run.

5. Expecting symbol keys in JSON

Broken assumption:

require 'json'
car = { make: 'bmw' }
puts car.to_json

Problem:

  • JSON keys are strings, not Ruby symbols.

Result:

{"make":"bmw"}

Comparisons

ApproachWorks in plain Ruby?Requires require 'json'?Notes
hash.to_jsonYes, usually after loading JSONYesConvenient and common
JSON.generate(hash)YesYesExplicit and clear
JSON.pretty_generate(hash)YesYesBest for readable output
render json: hash in RailsRails onlyNo manual require in normal Rails useRails handles serialization

to_json vs JSON.generate

MethodBest useAdvantageLimitation
to_jsonQuick object serializationShort and readableDepends on method availability
JSON.generateExplicit serialization in Ruby scriptsClearer intentSlightly more verbose

Ruby Hash vs JSON

Ruby HashJSON
In-memory Ruby objectText string
Can use symbol keysKeys are strings
Used inside Ruby codeUsed for storage and transfer
Example: { make: 'bmw' }Example: {"make":"bmw"}
Take Quiz

Cheat Sheet

require 'json'

Convert hash to JSON

car = { make: 'bmw', year: '2003' }
car.to_json

Explicit conversion

JSON.generate(car)

Pretty output

JSON.pretty_generate(car)

Key rules

  • Ruby hash keys can be symbols or strings.
  • JSON object keys are always strings.
  • JSON output is a string, not a hash.

Common fix for undefined method 'to_json'

require 'json'

Good default in plain Ruby

require 'json'
JSON.generate(data)

Example

require 'json'

car = { make: 'bmw', year: '2003' }
puts car.to_json
# => {"make":"bmw","year":"2003"}

FAQ

Why does hash.to_json work in Rails but not in plain Ruby?

Rails often loads JSON-related functionality for you. In plain Ruby, you usually need require 'json' first.

What is the simplest way to convert a Ruby hash to JSON?

Use:

require 'json'
JSON.generate(hash)

or:

require 'json'
hash.to_json

Is to_json built into every Ruby object?

Not always in the way beginners expect. Availability depends on the loaded libraries and environment.

Are Ruby symbol keys preserved in JSON?

No. JSON object keys become strings.

What is the difference between a hash and a JSON string?

A hash is a Ruby data structure. JSON is text used to represent data.

Should I use to_json or JSON.generate?

In plain Ruby, JSON.generate is often clearer because it makes the conversion explicit.

How do I get formatted JSON output in Ruby?

Use:

require 'json'
JSON.pretty_generate(hash)
Take Quiz

Mini Project

Description

Build a small Ruby script that creates a product record as a hash and exports it as JSON. This demonstrates how Ruby data is prepared for APIs, files, or external services.

Goal

Create a Ruby script that turns a hash into both compact JSON and pretty-printed JSON.

Requirements

  • Create a hash with at least three keys, such as name, price, and in_stock.
  • Load the JSON library before converting the hash.
  • Output both compact JSON and pretty-formatted JSON.
  • Use valid Ruby variable names consistently.
Take Quiz

Keep learning

Related questions

View more