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.

Paste one representative object, or an array of them — fields missing from some elements are marked optional.
TypeScript
  

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?: T vs a: T | null); Go collapses them into a pointer with omitempty; Python uses | None with a default; Rust uses Option<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 required a and an optional b.

Field naming across languages

JSON keys are frequently not valid identifiers in the target language, and each language solves that differently:

LanguageKey content-type becomesHow the original is preserved
TypeScript"content-type"Quoted property — the key is kept exactly.
GoContentType`json:"content-type"` struct tag.
Pythoncontent_typeNothing automatic — you need an alias in your (de)serializer. The tool warns when this happens.
Rustcontent_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 null for 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": [] becomes unknown[] / []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 inferring Date / time.Time from a string that happens to look like a date would be wrong as often as it is right.