JSON to Ruby Converter Online — Generate Hash/Class

Generate Ruby classes from any JSON payload — attr_accessor properties, dual symbol-or-string keyed initializers, and nested classes for Rails, Sinatra, and pure Ruby. 100% in your browser.

What is a JSON to Ruby converter?

A JSON to Ruby converter reads a JSON sample and emits idiomatic Ruby classes that mirror the JSON shape — attr_accessor for every key, an initializer that accepts either symbol- or string-keyed hashes, and nested classes for nested objects. The output drops straight into Rails, Sinatra, Hanami, or a pure Ruby script and works with the standard JSON.parse from the Ruby stdlib.

Writing wrapper classes by hand for a 200-field API payload wastes hours and is error-prone — a single typo in an attribute name silently leaves a value as nil. OpenFormatter's converter walks the JSON tree once, generates idiomatic Ruby, and runs entirely in your browser so internal API responses never leave your machine.

How to generate Ruby classes from JSON — 4 steps

  1. Paste a real JSON response. Use a representative sample — the converter inspects every key in the JSON object to build the attr_accessor list. Booleans must be true/false, numbers must be unquoted.
  2. Click Convert. The tool emits a Root class plus one separate class per nested object, each with attr_accessor and a flexible initializer.
  3. Copy and paste into your IDE. Each class is independent — split them into separate .rb files in your app/models/ or lib/ folder.
  4. Instantiate. Root.new(JSON.parse(json, symbolize_names: true)) — the initializer handles both symbol and string keys so the call is identical with or without symbolize_names.

JSON to Ruby type mapping

Sample JSON

{
  "id": 42,
  "name": "Ada Lovelace",
  "active": true,
  "score": 98.5,
  "address": { "city": "London" },
  "tags": ["admin", "engineer"]
}

Generated Ruby class

# frozen_string_literal: true

class Root
  attr_accessor :id, :name, :active, :score, :address, :tags

  def initialize(data = {})
    @id      = data[:id]      || data['id']
    @name    = data[:name]    || data['name']
    @active  = data[:active]  || data['active']
    @score   = data[:score]   || data['score']
    @address = data[:address] || data['address']
    @tags    = data[:tags]    || data['tags']
  end
end

class Address
  attr_accessor :city

  def initialize(data = {})
    @city = data[:city] || data['city']
  end
end

Idiomatic Ruby PORO

attr_accessor for every key, an initializer that accepts hashes from JSON.parse with or without symbolize_names — the same pattern used inside the Stripe and Twilio Ruby SDKs.

Nested classes

Every nested JSON object becomes its own top-level Ruby class so you can require_relative them independently and unit-test them in isolation.

Client-Side Only

JSON is parsed in JavaScript inside the browser. Internal Rails API responses, tokens, or PII never reach a server.

Common use cases

  • check_circleGenerating Rails API client wrappers from a third-party JSON response
  • check_circleBuilding Sinatra/Hanami DTOs from a frontend JSON payload
  • check_circleProducing Sidekiq job argument value objects from JSON
  • check_circleModelling Stripe, Slack, GitHub webhook event payloads as PORO classes
  • check_circleGenerating presenters / view models on top of ActiveRecord query results
  • check_circleBuilding config wrapper classes from a JSON settings file
  • check_circleModelling JSON-RPC or GraphQL response payloads in a Ruby SDK
  • check_circleConverting a one-off JSON export into typed objects for a Rake migration script

Why client-side generation matters

The JSON you paste often contains real customer data, OAuth tokens, signed URLs, or internal field names you do not want indexed by a third-party converter. OpenFormatter generates the Ruby entirely in JavaScript on your device — open the Network tab in DevTools and you will see zero requests when you click Convert. Safe for enterprise use, safe behind a corporate proxy, safe when the API contract is itself confidential.

Need other JSON tooling?

Format JSON, validate JSON, or generate types for other dynamic languages — all browser-side.

Frequently Asked Questions

Class with attr_accessor or symbol-keyed hash?

The generator emits a class with attr_accessor for every JSON key plus an initialize(data = {}) method that accepts both symbol-keyed (data[:name]) and string-keyed (data["name"]) hashes — that is the same pattern used internally by Stripe, Twilio, and the official Ruby SDKs. If you only need a value-object wrapper without methods, replace the class with a Struct.new(:id, :name, ...) one-liner; if you want immutability use Data.define(:id, :name, ...) (Ruby 3.2+).

How do I deserialize a JSON string into the generated class?

require 'json'; data = JSON.parse(json_string, symbolize_names: true); root = Root.new(data) — the symbolize_names option is what makes data[:name] work directly. Without it, JSON.parse returns string keys and the generated initializer falls back to data['name'] thanks to the || operator.

Will the generated class work with Rails?

Yes. The generated class is a plain Ruby object — drop it into app/models/ if it represents a database record (then have it inherit from ApplicationRecord), or into app/services/ as a value object. For ActiveModel-style validations and serializers add include ActiveModel::Model and include ActiveModel::Serializers::JSON.

How are nested JSON objects modelled?

Each nested object becomes its own top-level Ruby class so you can require_relative each one separately. The parent class stores the nested data as the raw hash — to get a typed nested instance, call Address.new(@address) inside an accessor method or wire the conversion in initialize for eager instantiation.

How are JSON arrays of objects handled?

Arrays of primitives (strings, integers) come through as plain Ruby arrays — no transformation required. Arrays of nested objects come through as arrays of hashes; map them through the matching class: @items = data[:items].map { |item| Item.new(item) } in your initialize.

Can I use this with the Sidekiq, Sequel, or ROM gems?

Yes. The generated PORO works as a Sidekiq job argument (after to_h) and as a presenter on top of a Sequel or ROM result row. The accessors and initializer signatures are deliberately stdlib-only so they compose with any Ruby framework.

How are JSON keys with hyphens or Ruby reserved words handled?

A JSON key like "user-id" is invalid as a Ruby instance variable; rename the symbol after copying (e.g. :user_id) and translate inside initialize: @user_id = data[:"user-id"]. Reserved words like "class" or "end" cannot be method names — suffix them (class_name) and translate the same way.

Is the JSON uploaded to your servers?

No. Conversion runs entirely in your browser via JavaScript. Open DevTools → Network and click Convert — no requests are made. JSON containing API keys, internal field names, or PII never leaves your machine.

JSON to Ruby Converter Online — Generate Class