FormatterHQ

JSON to Ruby Class Generator

Generate typed Ruby models from JSON with dry-struct and dry-types: strict attribute types, optional values and helpers that parse and validate JSON.

Input JSON
Output RUBY
Ready.

How to use the JSON to Ruby

  1. Paste your JSON sample (an object, or an array of objects) into the Input editor, or use Sample, Upload file or Load URL, or press Sample to try one.
  2. Set the Top-level class name, for example Task; it is converted to PascalCase. Nested types are named after their property keys.
  3. Leave Types only (no helpers) off for from_json! / to_json helpers; tick it for the struct definitions alone.
  4. Press Generate (it also re-runs automatically as you edit), then use Copy or Download.

JSON to Ruby with dry-struct

Ruby's JSON.parse returns hashes with string keys and no guarantees about their contents. This JSON to Ruby generator produces typed models built on the dry-rb gems: each object shape becomes a Dry::Struct subclass, and every attribute has a type from dry-types. Constructing a struct with a wrong type raises an error immediately, which keeps bad data out of the rest of your application.

Example

{ "id": 42, "title": "Write docs", "done": false,
  "owner": { "name": "Ada", "email": null },
  "subtasks": [ { "title": "Outline", "estimate": 2 }, { "title": "Draft" } ] }
require 'json'
require 'dry-types'
require 'dry-struct'

module Types
  include Dry.Types(default: :nominal)
  Integer = Strict::Integer
  String  = Strict::String
  Bool    = Strict::Bool
  Nil     = Strict::Nil
end

class Subtask < Dry::Struct
  attribute :title,    Types::String
  attribute :estimate, Types::Integer.optional
end

class Task < Dry::Struct
  attribute :id,       Types::Integer
  attribute :title,    Types::String
  attribute :done,     Types::Bool
  attribute :owner,    Owner
  attribute :subtasks, Types.Array(Subtask)
end

Parsing JSON with the helpers

With Types only off, each struct gets class methods from_dynamic! (from a parsed hash) and from_json! (from a string), plus to_dynamic and to_json. They map JSON keys to attributes and apply the strict types, raising an error when the data does not match:

task = Task.from_json!(File.read("task.json"))
puts task.subtasks.first.title
puts task.to_json

The generated file notes that it "may look unusually verbose for Ruby"; that verbosity is the validation.

How types are inferred

Whole numbers use Types::Integer, decimals a Types::Double that accepts floats and integers, strings Types::String and booleans Types::Bool. Arrays are Types.Array(T) and nested objects their own Dry::Struct classes. Attributes missing from some objects or sometimes null get .optional. Because every type is Strict, a string where an integer is expected is rejected rather than coerced, which is the behavior you want at an API boundary.

Notes

  • Add dry-struct and dry-types to your Gemfile.
  • Attribute names that would clash with methods already defined on Dry::Struct are renamed; for example, a name key becomes owner_name in the Owner struct, while the helpers still read the original name key.
  • Dates are typed as strings; parse them with Time.iso8601 where needed.
  • In Rails you might prefer ActiveModel or plain POROs; the attribute list is still a good starting point.

Format the result with the Ruby Formatter. For Crystal, a language with Ruby-like syntax and compile-time types, see JSON to Crystal. Generation runs in your browser.

Frequently asked questions

Which gems does the generated Ruby code need?
dry-struct and dry-types, plus Ruby’s built-in json library. Add the two gems to your Gemfile and run bundle install.
Why was a property renamed?
Some names, such as name, conflict with methods Dry::Struct already defines, so the attribute gets a prefixed name. The helper methods still map it to the original JSON key.
What happens if the JSON has the wrong type?
The strict dry-types raise an error when the struct is built, naming the attribute that failed, instead of letting the bad value through.
Can I use plain Ruby classes instead?
Tick Types only to see the attribute list, then turn it into a Struct, Data (Ruby 3.2+) or a plain class if you do not want the dry-rb dependency.

Last updated September 26, 2026

Related tools