Generate plain, dependency-free Java classes from a JSON sample — optional fields boxed so they can be null, List types inferred from every element, renamed fields keeping their JSON key in a comment. Free, no sign-up — runs locally in your browser.
Why generate Java classes from a sample?
Java's JSON libraries — Jackson, Gson, Moshi — are happiest
with an explicit class per shape, public fields or accessors
declared, types chosen. Hand-writing those classes from a
sprawling API response is exactly the kind of mechanical work
that eats an afternoon and hides typos. The sample contains
the facts: which keys exist, which types they carry, which
are sometimes missing. This converter reads those facts off
the JSON and writes dependency-free classes (no annotations,
no imports beyond java.util.List when a list
appears), so you start from correct scaffolding and add the
framework details yourself.
How to use this tool
- Paste the JSON — ideally a real response. A sample where every optional field happens to be present will over-promise; see the boxing rule below for why that matters.
- Name the root class (
Order, SearchResponse…); nested classes are named after their keys automatically. - Press Generate Java. If the root is a single object, the classes follow the heading comment directly; a root array generates from the element shape.
- Read the notes: each lists a slot typed
Object and why. Then copy or download as a .java file. - In your project, add the annotations your mapper needs — the
// JSON key: comments mark exactly the fields whose names could not survive translation.
The rules it follows
Naming. Classes are PascalCase, fields
camelCase, derived from the JSON keys; a key that cannot
become a legal Java identifier is prefixed or adjusted and
its original spelling recorded in a comment — never dropped.
Optionality. A key present in every sighting
is a primitive; a key missing anywhere is boxed and nullable,
because that is the truth the sample tells.
Numbers. Whole numbers are long,
fractional ones double, and a slot mixing the
two widens to double. Merging.
Array elements merge into one class; identical shapes
deduplicate. Scope. No records, no builders,
no annotations, no package line — plain classes you can drop
into any codebase and extend.
Worked example
For an invoice whose second line item has no discount:
{
"invoice_id": 881,
"total": 129.5,
"lines": [
{ "sku": "A-1", "qty": 2, "discount": 0.1 },
{ "sku": "B-7", "qty": 1 }
]
}
the converter produces (note the comment and the boxed Double):
public class Root {
// JSON key: "invoice_id"
public long invoiceId;
public double total;
public List<Line> lines;
}
public class Line {
public String sku;
public long qty;
public Double discount;
}
Frequently asked questions
Why are some numeric fields long and others Long?
That distinction is the generator being precise about optionality. A field that appears in every object in the sample is a primitive (long, double, boolean) — fast and null-free. A field missing from even one array element is declared with the boxed type (Long, Double, Boolean), because in Java the only way a field can say "this key was absent" is to be null, and primitives cannot be null. If you always populate such a field in real data, the sample — not the generator — is what needs to grow.
Where are the Jackson or Gson annotations?
Deliberately absent — the classes carry no library dependency, so they compile anywhere. The one concession to real-world JSON is in the comments: when a JSON key is not a legal or sensible Java identifier ("first_name", "@type", a key starting with a digit), the field gets a comment naming the original key — exactly the information you need to add an @JsonProperty annotation in your framework of choice. Everything representable is represented; the library-specific spelling is left to you because the generator cannot know which library you use.
How are nested objects and arrays of objects typed?
Each distinct object shape becomes its own public class, named in PascalCase after the key that holds it. Arrays become List<T>, with T inferred from all elements together — so an array of objects yields List<User> where User's fields are the union of every element's keys, and fields missing from some elements are the boxed, nullable ones. Identical shapes are emitted once and shared; two different shapes fighting for one name get numeric suffixes.
What does Object in the output mean?
The same honesty rule as the other converters on this site: Object marks a slot the sample could not type precisely — a null value (Java has no null literal type), a mixture of unrelated types across the sample, or an empty array whose element type is unknowable. Every Object is listed in the notes above the result with the reason. Replacing those with real types is a modelling decision, and the notes exist so you make it deliberately rather than discovering it at runtime.
Does a JSON integer always become long?
Yes — JSON has a single number type, and int would silently overflow on values a sender is perfectly entitled to send (timestamps in milliseconds, snowflake IDs, counters past two billion). long is the safe default; narrowing a specific field to int is a one-word edit when you know its range. Values with a fraction become double. A caution: JSON cannot distinguish 1 from 1.0, so a field always sent as whole numbers will infer as long even if you think of it as a double — widen that field manually if its semantics demand it.