Why generate types at all
Typed models catch mistakes early. When the response of an API is described by an interface or a class, your editor completes field names, the compiler notices a misspelled key and a renamed field shows up as an error instead of a silent undefined or null at runtime. Writing these types by hand for a response with fifty fields and three levels of nesting takes time and is easy to get wrong.
A generator does the repetitive part in a second. The result is a good first draft that you then review, rename where needed and commit.
Try it here: JSON to Code
Open the full tool pageWhat a generator infers from your sample
Everything comes from the values in your JSON. That is why the quality of the sample matters more than anything else.
| In the JSON | Inferred as | Example |
|---|---|---|
| Text | string | "name": "Alex" |
| Whole number | int, or long above 2,147,483,647 | "id": 42 |
| Number with a decimal point | double or float | "price": 19.0 |
| true or false | boolean | "active": true |
| Text in ISO date format | date type, if enabled | "created": "2026-10-27T09:30:00Z" |
| null in some items | nullable type | "phone": null |
| Key missing in some items | optional field | "discount" only in one item |
| Object | a new named type | "address": { ... } |
| List of objects | list of one merged type | "items": [ { ... }, { ... } ] |
Give it a sample with variety
A generator can only describe what it sees. If your sample has one order with one item, every field looks required and no field looks nullable. If it has a list of orders where some have a discount and some do not, the discount field is correctly marked optional.
So before you generate, collect a response with several items, ideally including edge cases: a customer without a phone number, an order without items, a product with a decimal price. Put them in one array at the top level and the generator will merge all of them into one type per shape.
- Fields that are null in every item get a general type such as unknown, object or Any, because the real type is not visible.
- Empty lists become lists of unknown items for the same reason.
- A field that is a number in one item and text in another becomes a union in TypeScript and a general type in other languages.
- Large IDs above 2^53, such as some database keys, are safer as text. JavaScript cannot represent them exactly as numbers.
Names, attributes and conventions
JSON keys often follow the style of the backend, for example snake_case from Python or Ruby, while your client code uses another. A good generator renames fields to the convention of the target language and keeps the original key in an attribute, so serialization still matches the data.
| Language | Field names | How the JSON key is kept |
|---|---|---|
| TypeScript | Unchanged | Not needed; unusual keys are quoted |
| C# | PascalCase | [JsonPropertyName] or [JsonProperty] |
| Python | snake_case | Field(alias=...) in Pydantic |
| Go | Exported, with ID and URL | json:"key" struct tags |
| Java | camelCase | @JsonProperty (Jackson) |
| Kotlin | camelCase | @SerialName (kotlinx.serialization) |
Types are not validation
A TypeScript interface disappears when the code is compiled. If the API sends something else than the interface promises, nothing stops it at runtime. The same is true for plain classes in most languages: the deserializer fills what it can and leaves the rest empty.
If the data comes from outside your control, validate it when it arrives. In Python, Pydantic models do this out of the box, which is a good reason to choose that style in the generator. In TypeScript, libraries that check data at runtime can be written from the generated interfaces. In C#, Java and Kotlin, mark fields that must be present as required and let the serializer fail early.
A checklist before you commit
- Rename the top level type from Root to something meaningful, such as Order.
- Review every field typed unknown, object, Any or JsonElement and replace it with the real type.
- Check numbers: is a price really a double, or should it be a decimal type for money?
- Check dates: do you want them as text, or as a date type with a known time zone?
- Decide which optional fields are truly optional and which only happened to be missing in the sample.
- Merge types that the generator kept apart only because their samples differed slightly.