JSON to TypeScript / Go / Rust
Paste any JSON sample. Get clean TypeScript interfaces, Go structs, or Rust types with serde tags — fast, lightweight, and ready to paste into your code.
What this converter does
It walks a JSON sample, infers a type for every value, and emits an idiomatic type definition in your chosen language. Objects become interfaces (TypeScript), structs (Go, Rust), and nested objects produce sibling type definitions. Arrays of objects unify their element shapes — fields present in some items but not others are marked optional, and primitive values that vary (string in some items, integer in others) collapse to a union or to serde_json::Value in Rust. No data is sent anywhere — the entire inferrer runs in your browser.
How to use it
Paste a representative JSON payload (one record from your API response, ideally), pick the target language, and copy the result. If your JSON has multiple instances of the same shape (a paginated list, for example), include the array — the inferrer learns more from variance. The casing toggle renames fields in the output without touching the JSON keys themselves; for Go and Rust the original key is preserved as a struct tag so serialisation round-trips.
Tips and gotchas
- Optional vs nullable: a field missing from some records becomes
?/Option<T>, but a field present everywhere with a literalnullvalue becomes a union withnull— the two are different and inferred separately. - Numbers: integers stay integers in Go and Rust (
int64,i64); floats becomefloat64/f64. TypeScript collapses both tonumberbecause the language doesn't distinguish. - Empty arrays:
[]infers tounknown[]/[]interface{}/Vec<serde_json::Value>— drop a sample item in to get a real type. - Field renaming: only the inferrer renames fields. Your JSON parser still needs to map keys — Go uses the
json:struct tag, Rust uses#[serde(rename = ...)].
Frequently asked questions
How does it handle arrays of mixed types?
[1, 2, "x"], the element type becomes number | string. If it contains [{a: 1}, {a: 1, b: 2}], the element becomes one object type with a required and b optional. In Go and Rust where unions don't have a clean equivalent, mixed primitives collapse to interface{} / serde_json::Value.Does it handle deeply nested structures?
Why are my Go field names PascalCase even when I picked preserve?
encoding/json. The original JSON key is preserved in the json: tag, so serialisation still produces the input casing.How is this different from heavyweight code generators?
Will my output compile?
use serde::{Deserialize, Serialize}; for Rust is included; Go's encoding/json is implicit). If your JSON keys collide with reserved words after renaming, Rust uses r# raw identifiers automatically.Is anything sent to a server?
JSON.parse and the inferrer is a small recursive function on this page. Open DevTools > Network and you'll see no requests fire while you type. Safe for production payloads, internal API responses, and anything you wouldn't paste into a hosted SaaS.
EN
PT
ES