JSON to Ruby Class

Convert JSON to Ruby Struct, Data.define or plain classes with from_h and to_h

A free JSON to Ruby converter: paste JSON and get Ruby classes back instantly. Choose a keyword-init Struct, an immutable Data.define (Ruby 3.2+) or a plain class with attr_accessor, each with from_h, from_json, to_h and to_json so it reads and writes the hash JSON.parse gives you. Types are inferred from the data and written as YARD comments, nested objects become their own classes, and members that would shadow a core method or a keyword are renamed so the file loads without warnings. Conversion runs entirely in your browser, so your JSON is never uploaded to a server.

Options on this page

Output formats: Struct (Keyword-init Struct with mutable members), Data (Immutable Data.define value object (Ruby 3.2+)), Class (Plain class with attr_accessor and a keyword constructor).

OptionWhat it does
Root Class NameNames the top-level Class.
Module (optional)Wraps the classes in nested module blocks. Acme::Models, acme.models and acme/models all give module Acme, then module Models.
Field Naming ConventionOne of snake_case, camelCase, Preserve Original. Defaults to snake_case.
Type for null valuesEither Object or String, used when a key is null in every sample.
Separate ClassesWrite each class to its own .rb file, each requiring the files it refers to with require_relative. Off (the default) puts every class in one file, so Copy All pastes into a single file that loads.
Map original JSON keysRead and write each member under the original JSON key. Without it a member only binds to a key spelled exactly like it, so a camelCase key is not read into a snake_case member.

How JSON values map to Ruby types

JSON valueRuby type
stringString
integerInteger
decimalFloat
true / falseBoolean (YARD)
ISO-8601 timestampString
arrayArray<T>
objectnested class
null or missing in some samplesT, nil
nullObject (configurable)

Example

Input JSON

{
  "id": 1,
  "product_name": "Wireless Mouse",
  "in_stock": true,
  "tags": ["electronics"]
}

Generated Ruby

# @!attribute [rw] id
#   @return [Integer]
# @!attribute [rw] product_name
#   @return [String]
# @!attribute [rw] in_stock
#   @return [Boolean]
# @!attribute [rw] tags
#   @return [Array<String>]
Product = Struct.new(:id, :product_name, :in_stock, :tags, keyword_init: true) do
  def self.from_h(hash)
    return nil if hash.nil?

    new(
      id: hash['id'],
      product_name: hash['product_name'],
      in_stock: hash['in_stock'],
      tags: hash['tags']
    )
  end

  def self.from_json(json)
    from_h(JSON.parse(json))
  end

  def to_h
    {
      'id' => id,
      'product_name' => product_name,
      'in_stock' => in_stock,
      'tags' => tags
    }
  end

  def to_json(*args)
    to_h.to_json(*args)
  end
end

Frequently asked questions

How do I convert JSON to a Ruby class?

Paste your JSON into the input pane and the Ruby classes appear beside it immediately. Set the root class name and an optional module, pick Struct, Data or Class, then copy the code or download it. Load it and call Root.from_json(json_string) to get an object, and to_json to write it back. Nested JSON objects become their own classes and arrays are mapped element by element.

Should I choose Struct, Data or Class?

Struct gives mutable members with a keyword constructor and works on every Ruby 2.5 and later. Data.define gives an immutable value object with the same API but needs Ruby 3.2 or later. A plain class has attr_accessor members and works anywhere. All three expose from_h, from_json, to_h and to_json, so you can switch without touching the calling code.

Why does the generated code use from_h instead of a JSON library?

Ruby has no schema-driven deserializer in the standard library, so the classes read the Hash that JSON.parse returns. Each from_h builds the object member by member and hands nested objects to their own class, which keeps the code dependency-free: it needs only the json standard library.

What happens to keys that are Ruby keywords or core method names?

A member named class, end, hash, to_h, members and so on would break the file or replace a method Ruby relies on, so it gets a trailing underscore (class_). The JSON key is kept: with Map original JSON keys on, from_h reads and to_h writes the original key.

Why are timestamps a String?

Time.parse and DateTime.parse reformat a timestamp when it is written back, adding fractional digits or changing the zone, so the document would no longer round-trip. A timestamp stays a String; parse it where you need a Time.

Is my JSON uploaded anywhere?

No. Parsing, type inference, and code generation all run in your browser using JavaScript. Your JSON is never sent to a remote server, and there is no account to create. The page keeps your last input and settings in your own browser (localStorage) so they survive a reload; nothing is stored anywhere else.

Is it safe to paste confidential JSON, such as API responses or customer data?

The conversion itself never transmits your JSON, so a confidential payload does not leave your machine. You can verify this: open your browser DevTools, switch to the Network tab, and convert something — no request carries your data. Two things to know: your last input is saved in your browser's localStorage (clear site data to remove it), and the Copy Link button embeds your JSON in the link, so anyone who opens that link, and the server that receives the request, can see it. Only share such links where you are comfortable with that.

Does it cost anything?

No. The generator is free to use with no sign-up and no usage limits.

How are nested objects handled?

Each nested JSON object becomes its own named type, derived from the key it appeared under. Arrays of objects are widened across every element, so a field that is a whole number in one element and a fraction in another gets a type that holds both.

Other languages

More JSON tools