JSON to Ruby

Input
Output

JSON to Ruby

Paste a JSON sample, such as an API response, and Bracely writes Ruby dry-struct classes for it. Each object becomes a Dry::Struct class with typed attributes, so a hash from JSON.parse is checked and turned into an object in one call.

Example: invoices from a billing webhook

Two invoices, one paid with a paid_at time and one not. Each object becomes a Dry::Struct; keys arrive as strings from JSON.parse, so transform_keys turns them into symbols, and paid_at uses attribute? because it can be missing:

Input

[
  {
    "id": "in_1001",
    "number": "INV-2026-0042",
    "amount_due": 4999,
    "currency": "inr",
    "paid": false,
    "customer": {
      "id": "cus_77",
      "email": "ananya@example.com"
    },
    "lines": [
      {
        "description": "Pro plan",
        "amount": 4999
      }
    ]
  },
  {
    "id": "in_1002",
    "number": "INV-2026-0043",
    "amount_due": 0,
    "currency": "inr",
    "paid": true,
    "customer": {
      "id": "cus_78",
      "email": "kabir@example.com"
    },
    "lines": [],
    "paid_at": "2026-10-29T10:00:00Z"
  }
]

Output

require "dry-struct"

module Types
  include Dry.Types()
end

class Line < Dry::Struct
  transform_keys(&:to_sym)

  attribute :description, Types::String
  attribute :amount, Types::Integer
end

class Customer < Dry::Struct
  transform_keys(&:to_sym)

  attribute :id, Types::String
  attribute :email, Types::String
end

class Invoice < Dry::Struct
  transform_keys(&:to_sym)

  attribute :id, Types::String
  attribute :number, Types::String
  attribute :amount_due, Types::Integer
  attribute :currency, Types::String
  attribute :paid, Types::Bool
  attribute :customer, Customer
  attribute :lines, Types::Array.of(Line)
  attribute? :paid_at, Types::String
end

InvoiceList = Types::Array.of(Invoice)

How do I use the JSON to Ruby?

  1. Paste a JSON sample.
  2. Set the root type name, for example Order.
  3. Copy the Ruby code into your project.

What does the JSON to Ruby do?

  • Dry::Struct classes with Types::String, Integer, Float and Bool
  • attribute? for keys that can be missing
  • Nested structs and Types::Array.of(...) for lists
  • Nested objects become their own named types
  • 20 other languages from the same sample, including TypeScript

When to use the JSON to Ruby

Rails apps and Ruby services usually pass JSON around as hashes, so a typo in a key or an unexpected type fails far from where the data came in. dry-struct turns a hash into a typed object and fails at once if it doesn't fit. Paste a webhook or API payload and copy the structs for it.

Each object becomes a Dry::Struct class with typed attributes: Types::String, Integer, Bool, and Types::Float | Types::Integer for numbers that are sometimes whole. Lists are Types::Array.of(…) and nested objects their own struct. transform_keys(&:to_sym) lets JSON.parse's string keys in. A key missing from some items uses attribute?, as paid_at does in the example.

Frequently asked questions

How do I build an object from the JSON?
Invoice.new(JSON.parse(body)) checks every attribute and returns the struct, or raises Dry::Struct::Error naming the field that didn't fit. You need the dry-struct gem (and dry-types with it).
A key can be there with a null value. What then?
attribute? only allows the key to be missing. To allow null as well, make the type optional: attribute? :paid_at, Types::String.optional.
How does it pick Ruby types?
From the values in your sample: whole numbers, decimals, text, true/false, arrays and nested objects. When array items disagree, the field is made optional or widened.
Can I generate other languages?
Yes. Change Language to any of the others: TypeScript, Go, Python, Pydantic, Java, C#, Kotlin, Swift, Rust, Scala, Dart, PHP, Zod, TypeBox, Valibot, Yup, GraphQL, Protobuf, Prisma and Drizzle.
Is my data uploaded?
No. Bracely runs entirely in your browser, so nothing you paste or open leaves your device.

More JSON tools

Bracely has 104 JSON tools in one page. Related ones:

Runs entirely in your browser. Nothing you paste is uploaded. Made by Saurabh Pagrut · About · Privacy policy
Last updated · Version 6.1 · Changelog
Saurabh Pagrut on GitHub · LinkedIn · X · YouTube · Instagram