# JSON to Typed Model

> Turn a JSON sample into a typed model: TypeScript interfaces, a Java record with Jackson annotations, a Kotlin data class, a Go struct or a Python dataclass.

Source: https://www.revquix.com/tools/json-to-types
Cost: free, no signup

---

Paste a real response and get a model for it. Array elements are merged rather than sampled, identical shapes are shared, and a field that was ever null comes out nullable - in whichever of the five languages you work in.

## At a glance

- Takes: A JSON sample - a whole response works better than one element
- Returns: TypeScript, a Java record, Kotlin, a Go struct or a Python dataclass
- Handles: Merged array elements, shared shapes, nullable kept apart from optional
- Privacy: Runs in your browser - nothing you paste is uploaded

## Three decisions that make the output usable

Array elements are merged, not sampled. A generator that types an array from its first element produces a model missing every field that element happened to lack. Every element is unified here instead, and a field absent from some of them becomes optional - which is almost always the truth about the API that produced the sample.

Identical shapes are shared. An object with a from and a to carrying the same fields produces one type used twice, not two identical declarations under different names. Structural identity is decided on the field list and the field types, so the output stays as small as the data actually is.

Nullable and optional are different facts. Optional means the key was absent from some element; nullable means it was present and its value was null. A field that is always there and sometimes null is a nullable string, not a required one. Conflating the two produces a model that type-checks and then throws on the first null, and it is the commonest defect in generators of this kind.

## Why the Java output is a record

The well-known converters own the TypeScript query, and none of them emits a Java record - the shape a codebase written after Java 16 actually wants. A bean with thirty lines of getters is not a model, it is a chore.

So the Java emitter produces a record with Jackson annotations wherever the wire name differs from the Java one, which for a snake_case API is most fields. Kotlin gets a data class with kotlinx.serialization annotations on the same principle.

- TypeScript interfaces, with optional and nullable spelled separately
- Java records, annotated only where the names actually differ
- Kotlin data classes with SerialName and nullable types
- Go structs with json tags, and a pointer where the field is nullable
- Python dataclasses, with defaulted fields ordered after required ones

## Naming

Only the root type needs a name. Everything else is named after the field that holds it, singularised for an array - a bookings array of objects produces a Booking. That is what makes the output read like something a person wrote rather than a numbered list of anonymous types.

## What it cannot know

A model generated from one sample describes that sample. A field that was only ever null in it has no knowable type, and is emitted as the target’s open type with a warning rather than guessed at.

An integer that happens to have no decimal part is typed as an integer, which is wrong if the API can return a fraction. A one-element array makes every field look required. And an id above two to the fifty-third has already been rounded by the JSON parser before the generator sees it, so a very large numeric id is better modelled as a string.

It does not read an OpenAPI document, infer enums from repeated strings, or detect a date inside a string. Read the generated types before you commit them.

## Questions people ask

### Why is my field optional when the API always sends it?

Because it was missing from at least one element of the sample you pasted. A field is marked optional when some observed object lacked the key entirely. If the API really always sends it, paste a wider sample - or delete the marker yourself, since a sample cannot prove what the contract says.

### What is the difference between the question mark and the null in the output?

They are different facts. The question mark means the key was sometimes absent; the null means the key was present and its value was null. A field can be both. Most generators collapse the two, which produces a model that compiles and then throws the first time the API sends an explicit null.

### Can I generate a model for a very large id?

You can, but read the warning if one appears. A JSON parser cannot represent an integer above two to the fifty-third minus one exactly, so a nineteen-digit id has already been rounded before any generator sees it. For ids of that size the correct model is usually a string, and the tool says so rather than quietly emitting a long.

### Does it support enums, dates or OpenAPI input?

No to all three, deliberately. A repeated string is not evidence of an enum, a date inside a string is indistinguishable from any other string, and an OpenAPI document already carries types - generating from a schema is a different tool with a different contract. This one infers from data and says only what the data supports.

### Is my payload sent anywhere to be analysed?

No. Parsing and generation both happen in your browser and there is no request on any code path. That matters more than usual here, because the natural thing to paste is a real API response - which routinely contains customer names, email addresses and identifiers.
