JSON to Code
Turn a JSON sample into types for TypeScript, Go, Rust, Python, Java, Kotlin, Swift or C#, or a Zod schema, keeping each original key via its rename tag.
Several samples? Paste them one after another — JSON Lines works — and the types cover every one.
Turn JSON into typed code
Paste a JSON sample, pick your target language, and get ready-to-paste type definitions — nested
objects become nested types, arrays become typed lists, and field types are inferred from the values.
Supports TypeScript interfaces, Go structs (with json tags),
Rust structs (serde), Python dataclasses, Java classes
(Jackson @JsonProperty), Kotlin data classes (kotlinx.serialization),
Swift Codable structs and C# classes (System.Text.Json) — or, instead of types, a
Zod schema with its z.infer type. Wherever a key has
to be renamed to be a legal identifier — first_name to firstName — the original key
is kept in the annotation or tag that language uses, so the code decodes the JSON it was generated from.
TypeScript quotes an awkward key rather than renaming it; Python dataclasses have no such annotation, so
there a renamed field is matched to its key only by the from_dict that
“Add the code that reads the JSON” writes.
Everything runs in your browser — your JSON is never uploaded.
The boxes under the options are all off by default, so the plain output does not change until you tick a box.
Enums for strings that keep repeating turns a field that repeats a few strings into an enum in each
language; Maps for objects keyed by ids reads a dictionary keyed by ids as one map type —
Record<string, T>, map[string]T, Dictionary<string, T> —
instead of a class per key; Types of their own for dates, UUIDs and URLs gives those strings the type
each language’s decoder fills, such as time.Time, datetime or Guid; and
Add the code that reads the JSON adds the function that parses it — UnmarshalRoot in Go,
parse_root in Rust, a Jackson fromJson in Java, and so on. Several samples pasted
one after another, JSON Lines included, are merged into one set of types, so a key only some of them have
comes out optional. Some switches belong to a single language and appear only beside it: Type aliases instead of interfaces, readonly on every property and Every property optional (?) for TypeScript, omitempty on every field for Go (a zero value, an empty string, false or an empty list is then left out when the struct is written back to JSON), Check each value’s type while reading (raises TypeError) for Python, and a Package field for Go, Java and Kotlin — Namespace for C# — that puts the declaration where that language expects it. Zod shows its own five in place of the four above: string formats (.email(), .url(), .datetime(), .uuid()) where every sample value agrees, a mixed array as z.tuple([...]), a sometimes-null field as .nullable(), .int() for whole numbers (on from the start), and z.enum or z.literal for strings that keep repeating. Rust structs and enums come with the use serde::{Deserialize, Serialize}; line their derives need. The language you pick is kept in the address — choosing Go writes ?lang=go — so the page’s address opens on it when shared. Under the code a line reminds you the types are a guess from this sample: a name such as Item2 means another shape had already taken that name, a list’s type name is a guessed singular (posts → Post), and a field missing from the sample is not there at all.
Frequently asked questions
Which languages are supported?
TypeScript, Go, Rust, Python (dataclasses), Java (Jackson), Kotlin (kotlinx.serialization), Swift (Codable) and C# (System.Text.Json), plus a Zod schema with its z.infer type. Choose the target from the Language dropdown; the same JSON generates code for any of them.
What happens to a JSON key that is not a valid identifier?
It is renamed to the idiomatic form for the language — first_name becomes firstName in Java and Kotlin, FirstName in C# — and the original key is recorded so the generated code still decodes: a Jackson @JsonProperty in Java, a kotlinx.serialization @SerialName in Kotlin, a [JsonPropertyName] attribute in C#, a json struct tag in Go, #[serde(rename = "…")] in Rust and a CodingKeys enum in Swift. TypeScript quotes the key instead. Reserved words are handled per language too — a trailing underscore in Java and Python, backticks in Kotlin and Swift, a raw identifier in Rust.
Does it handle nested objects and arrays?
Yes. Nested objects become nested type definitions and arrays become typed collections, with names derived from the field and root name you set.
Can the generated code read the JSON as well as describe it?
Yes — tick Add the code that reads the JSON. Each language then gets its parse step: parseRoot for TypeScript, UnmarshalRoot with encoding/json for Go, parse_root with serde for Rust, a from_dict classmethod on every dataclass plus root_from_json for Python, getters and a fromJson through Jackson’s ObjectMapper for Java, parseRoot with Json.decodeFromString for Kotlin, parseRoot with a JSONDecoder for Swift, and FromJson with JsonSerializer for C#. It is off by default, so the plain type definitions stay as they were.
Can I set a package, use type aliases or add runtime type checks?
Yes, where the language has them. A Package field (Go, Java, Kotlin) or Namespace (C#), empty by default, puts the declaration where that language wants it and refuses a name it would not compile. For TypeScript, Type aliases instead of interfaces writes each object as export type X = { … }. For Python, Check each value’s type while reading (raises TypeError) adds the reader and checks each field, naming the place, as in Root.age: expected int, got str.
Can I share a link that opens on my language?
Yes. The language rides in the address: choosing Go writes ?lang=go, and a link carrying it opens on Go, while TypeScript, the default, leaves the address clean; a ?lang= the page does not know is ignored. The link carries only the language, not your JSON.
Which Zod version does the Zod schema target?
Standard Zod builder syntax that works with Zod 3. Numbers are emitted as z.number().int() when every sample value is a whole number, unless Whole numbers as .int() is unticked.
With Zod chosen, can it write .email() or .uuid(), tuples or .nullable()?
Yes — tick them beside the language once Zod is chosen. The first three start off and Whole numbers as .int() starts on, so the schema is the plain one until you change them. Detect string formats adds .email(), .url(), .datetime() (with { offset: true } when a value carries an offset) and .uuid(), only where every sample string at that place agrees and only for values Zod itself accepts. Arrays of mixed kinds as z.tuple([...]) writes an array whose elements are of more than one kind as a tuple, and tuples of different lengths fall back to a list. A field that can be null as .nullable() drops z.null() from the union and puts .nullable() after what is left. Untick Whole numbers as .int() for a plain z.number().