JSON to TypeScript, Go, Python & Rust
Paste a JSON response and get typed declarations for TypeScript, Go, Python, or Rust — with optional and nullable fields inferred from the sample.
Runs entirely in your browser. Nothing you paste here is uploaded, logged, or sent to analytics.
What the inference actually does
The generator walks your JSON and builds one structural model, then emits it four ways. It is fully deterministic — the same input always produces the same declarations. Three rules do the interesting work:
- Integer vs float. A number with no fractional part infers as an integer
(
int64,int,i64). If any sample of the same field has a decimal, the field widens to a float. This is the one judgement call in the whole pipeline, and the sample you paste controls it — include a realistic value. - Optional vs nullable. These are different, and the languages disagree
about how different. A key absent from some objects in an array is optional; a
key present but null is nullable. TypeScript distinguishes both
(
a?: Tvsa: T | null); Go collapses them into a pointer withomitempty; Python uses| Nonewith a default; Rust usesOption<T>. - Array element merging. Every element of an array is merged into one
type, so
[{"a":1},{"a":2,"b":3}]yields a type with a requiredaand an optionalb.
Field naming across languages
JSON keys are frequently not valid identifiers in the target language, and each language solves that differently:
| Language | Key content-type becomes | How the original is preserved |
|---|---|---|
| TypeScript | "content-type" | Quoted property — the key is kept exactly. |
| Go | ContentType | `json:"content-type"` struct tag. |
| Python | content_type | Nothing automatic — you need an alias in your (de)serializer. The tool warns when this happens. |
| Rust | content_type | #[serde(rename = "content-type")]. |
Python is the one to watch. A dataclass field cannot be named content-type or
class, so the tool renames it and tells you — but the rename is not
round-trippable on its own, and you will need pydantic's
alias= or a custom __post_init__ to deserialize correctly.
Limits worth knowing
- One sample is one sample. If your API returns
nullfor a field only when a record is incomplete, and your sample happens to have it populated, the generated type will not be nullable. Paste a sample that includes the awkward cases. - Empty arrays carry no information.
"tags": []becomesunknown[]/[]interface, because there is genuinely nothing to infer from. - Structurally identical types are not deduplicated. Two nested objects with the same shape produce two declarations, named after their keys. This is intentional: merging them would be a guess about your domain model.
- Dates stay strings.
"2026-08-12T09:30:00Z"is a string in JSON, and inferringDate/time.Timefrom a string that happens to look like a date would be wrong as often as it is right.