JSON to Type Generator
Paste a JSON payload and get type definitions. Every array element is merged, so fields that appear only sometimes come out optional instead of silently wrong.
Paste a response, get a type
You have a JSON payload from an API and you need a type for it. Writing it by hand means reading every field, guessing which ones are nullable, and discovering the mistakes later at runtime. This tool reads the payload and emits a type definition for TypeScript, Go, Python dataclasses, Rust structs with serde attributes, or Java records.
The interesting part is not the field names — it is the inference. When a sample
contains an array of objects, the tool merges every element rather than
trusting the first one. If one object has a field the others do not, that field becomes
optional. If a field is null in one element and a string in another, it is
inferred as a nullable string rather than silently collapsing to one or the other.
Why merging matters more than it sounds
The naive approach — look at element zero, declare the type — produces types
that compile and then blow up in production. Real APIs are inconsistent: a field is
present on some records, absent on others; a number arrives as a string under some
conditions; a value that is always an object in testing turns out to be
null for a particular user.
Merging every element surfaces that inconsistency at generation time, which is exactly when you want to know about it. A field that is optional in the output is a field you must handle defensively in your code.
| Seen in the sample | Inferred type |
|---|---|
"name": "Ada" | string |
"count": 42 | number — widened to float if any element is fractional |
"ok": true | boolean |
"score": null | unknown — alone, null carries no information |
"score": null and 3.5 | number | null |
"tags": ["a"] and [1] | (string | number)[] |
[] | unknown[] |
A sample is evidence, not a contract. A generated type describes the data you pasted. If your sample has one record, an optional field will look required. Paste several records — ideally the odd ones — before you trust the output. For anything public-facing, the real answer is a schema from the provider, not inference from examples.
Empty arrays and nulls are genuinely ambiguous
An empty array tells you the field is a list and nothing about what is inside it. A
null tells you a value was absent and nothing about what it would have been.
Neither can honestly be narrowed to a concrete type, so this tool emits
unknown (or interface{}, Any,
serde_json::Value) rather than guessing. That is deliberately conservative:
a widening you can tighten later is far cheaper than a wrong guess that silently accepts
bad data.
Frequently asked questions
Why does it use interface{} in Go?
Because that is the honest translation of a value whose shape the sample does not pin down. Replace it with a concrete type once you know what the API actually sends.
Does it handle deeply nested objects?
Yes. Each nested object becomes its own named type, so the output stays readable instead of collapsing into one enormous inline literal. Names are derived from the key path, and deduplicated when two paths would collide.
Can I use this for a config file?
Yes, and it works especially well there, because a config file is usually a complete example rather than one record out of a million. Turn merging off if you want each field treated as required.
Is my data uploaded?
No. Parsing and generation happen in this page with no network request. It is safe to paste a payload containing customer identifiers or internal field names.
Privacy. Everything runs in your browser. Your JSON never leaves the device, which is the point — the payloads people need types for are usually the ones they would rather not paste into a stranger's server.