Ruby Academy · Lesson

JSON APIs

Returning JSON.

Lesson 3 of 413 steps

JSON APIs is a free Ruby Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Ruby Academy learning path, and your progress syncs across the web and the CoddyKit app. The Ruby Academy course includes 4 lessons in total.

Why JSON APIs?

JSON is the standard data format for web APIs. Clients send and receive structured data instead of HTML.

  • Language independent
  • Maps cleanly to Ruby hashes and arrays
  • Lightweight and human readable

Ruby's standard library handles JSON via the json module.

require 'json'

data = { name: 'Ada', langs: ['Ruby', 'Python'] }
puts data.to_json

Converting Ruby to JSON

Call to_json on a hash or array, or use JSON.generate.

  • Symbols and strings become JSON keys
  • Nested structures convert recursively
require 'json'

user = { id: 1, active: true, tags: ['admin'] }
puts JSON.generate(user)

Pretty Printing JSON

For readable output use JSON.pretty_generate.

  • Adds indentation and newlines
  • Great for debugging and logs
  • Avoid in production responses to save bytes
require 'json'

config = { server: { host: 'localhost', port: 4567 } }
puts JSON.pretty_generate(config)

Parsing JSON Input

Use JSON.parse to turn an incoming JSON string into Ruby objects.

  • By default keys are strings
  • Pass symbolize_names: true for symbol keys
require 'json'

raw = '{"name": "Ada", "age": 30}'
data = JSON.parse(raw)
puts data['name']
puts data['age']

Symbolized Keys

Symbol keys are convenient and slightly faster to look up.

  • Enable with symbolize_names: true
  • Be careful with untrusted input creating many symbols
require 'json'

raw = '{"city": "Istanbul"}'
data = JSON.parse(raw, symbolize_names: true)
puts data[:city]

Returning JSON from Sinatra

In a Sinatra route, set the content type and return a JSON string.

  • content_type :json sets the header
  • Return hash.to_json as the body
require 'sinatra'
require 'json'

get '/api/status' do
  content_type :json
  { status: 'ok', time: Time.now.to_i }.to_json
end

Reading a JSON Request Body

For POST APIs, read the raw body and parse it.

  • request.body.read gives the raw string
  • Parse it with JSON.parse
require 'sinatra'
require 'json'

post '/api/users' do
  payload = JSON.parse(request.body.read)
  content_type :json
  { created: payload['name'] }.to_json
end

Building an API Response Hash

Keep responses consistent by building a structured hash before serializing.

  • Wrap data under a data key
  • Include status and metadata
require 'json'

def api_response(data, status: 'ok')
  { status: status, data: data }.to_json
end

puts api_response({ id: 1, name: 'Ada' })

Handling Parse Errors

Malformed JSON raises JSON::ParserError. Always rescue it.

  • Return a 400 Bad Request to the client
  • Never let a parse error crash the app
require 'json'

begin
  JSON.parse('{ broken')
rescue JSON::ParserError => e
  puts "Invalid JSON: #{e.message}"
end

Serializing Arrays of Objects

Collections serialize naturally as JSON arrays.

  • An array of hashes becomes an array of objects
  • Use map to shape each record
require 'json'

users = [{ id: 1, name: 'Ada' }, { id: 2, name: 'Bob' }]
output = users.map { |u| { name: u[:name] } }
puts output.to_json

Custom to_json on Objects

You can teach a class how to serialize by defining to_json or as_json.

  • Convert internal state to a plain hash
  • Hide private fields from the API
require 'json'

class User
  def initialize(id, name)
    @id = id
    @name = name
  end

  def to_json(*)
    { id: @id, name: @name }.to_json
  end
end

puts User.new(1, 'Ada').to_json

Quick Check

Confirm your JSON API knowledge.

Recap

You learned to build JSON APIs:

  • require 'json' from the standard library
  • to_json / JSON.generate serialize Ruby to JSON
  • JSON.parse deserializes incoming JSON
  • Set content_type :json in Sinatra routes
  • Always rescue JSON::ParserError

Next you will explore Rack and middleware.

Free to start

Learn Ruby with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
29
Lessons
109

Frequently Asked Questions

Is the “JSON APIs” lesson free?

Yes — any 3 lessons of the Ruby Academy learning path, including “JSON APIs”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Ruby Academy course includes 4 lessons in total.

What will I learn in “JSON APIs”?

Returning JSON. You practise Ruby Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Ruby Academy?

No prior experience is required. Ruby Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.

How long does the “JSON APIs” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Ruby Academy lesson?

Yes. Every Ruby Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Sinatra Basics
  2. Routes and Params
  3. JSON APIs
  4. Middleware and Rack
← Back to Ruby Academy