Generate code from JSON
JSON All-in-One can inspect a sample JSON document and draft models for seven language targets: TypeScript, Python 3, Java, Kotlin, C#, Go, and Rust. Compare the target options here, then follow the language-specific guide for your application.
The important habit is review. Generated code is a starting point from observed data, not a complete API contract, business-rule validator, or promise that future responses will stay inside the same shape.
Start with the shape you actually receive
Skip the hello-world object and use a small sample that actually resembles your payload. For array payloads, two or more records help reveal optional fields, explicit null, enum-like strings, and mixed values that a one-record sample cannot expose.
This event fixture is enough to show several useful decisions: status looks like an enum candidate, metadata varies by record, profile can be null, and account_id is large enough that a native-number decision should be reviewed before a model lands in production.
[
{
"id": "evt_1001",
"account_id": 9007199254740993,
"status": "delivered",
"created_at": "2026-09-04T12:15:30Z",
"profile": { "email": "ada@example.dev", "tags": ["trial", "api"] },
"metadata": { "source": "webhook", "retry": false }
},
{
"id": "evt_1002",
"account_id": 9007199254740995,
"status": "queued",
"created_at": "2026-09-04T12:18:10Z",
"profile": null,
"metadata": { "source": "batch", "attempt": 2 }
}
]Pick the target by integration, not by habit
If the model is used at a web boundary, start with TypeScript so the frontend can review optional and nullable fields. If the next step is a Python data job, Python dataclasses give you clear annotations but still require a separate loading step.
For JVM services, Java supports class or record style and an optional Jackson serializer mode, while Kotlin focuses on data classes/classes and explicit nullability. For backend services, C#, Go, and Rust each need different choices around attributes, JSON tags, Serde, and numeric policies.
| Target | Best first question | Important caveat |
|---|---|---|
| TypeScript | Do I need interfaces or classes? | Types do not validate runtime JSON. |
| Python 3 | Will dataclasses be loaded by handwritten code? | The generated model is not Pydantic. |
| Java | Class, record, and Jackson or no serializer? | Jackson annotations do not install or configure Jackson. |
| Kotlin | Data class or class, and which package? | Serializer adapters are not implied. |
| C# | Record-style models or settable classes? | JSON-name mapping and special numeric codecs need review. |
| Go | Struct tags and native or big-number fields? | Custom decoding may be needed for non-native numbers. |
| Rust | Plain structs or Serde output? | Cargo features and deserialization must be checked. |
Review options before you copy
The shared controls cover language, supported style where available, serializer where available, enum generation, file layout, package or namespace where the language has one, and primitive policies for integers, decimals, date/time strings, and unknown JSON values.
Those controls are intentionally language-specific. TypeScript can choose interface or class and can map large integers to string, bigint, or BigNumber; Java can choose record or class and Jackson or None; Rust can choose serde or None. Python, Go, and Rust do not all expose the same style switches because the target languages do not solve the same integration problem.
TypeScript: export interface GeneratedRootItem { account_id: number; profile: GeneratedRootItemProfile | null; }
Python: @dataclass(slots=True) class GeneratedRootItem: account_id: int; profile: GeneratedRootItemProfile | None
Java: public record GeneratedRootItem(@JsonProperty("account_id") Long account_id, @JsonProperty("profile") GeneratedRootItemProfile profile /* nullable */) {}
Kotlin: data class GeneratedRootItem(val account_id: Long, val profile: GeneratedRootItemProfile?)
C#: public record GeneratedRootItem { public long AccountId { get; init; } public GeneratedRootItemProfile? Profile { get; init; } }
Go: type GeneratedRootItem struct { AccountId int64 `json:"account_id"`; Profile *GeneratedRootItemProfile `json:"profile"` }
Rust: pub struct GeneratedRootItem { pub account_id: i64, pub profile: Option<GeneratedRootItemProfile> }A practical review flow
- Open or paste the JSON you want to model.
- Run Codegen and select the target language.
- Turn enum generation on only when the observed strings really behave like a closed set.
- Choose primitive policies deliberately, especially for identifiers, money, timestamps, and arbitrary JSON blobs.
- Copy one generated file into a scratch project before adopting the full package.
- Add handwritten parsing, validation, serializer configuration, or domain rules separately.
What generation does not prove
A generated model can tell you what this sample looked like. It cannot prove that an API never omits a field, that a string enum is exhaustive, that a decimal is safe for binary floating-point math, or that a future version of the service will keep the same keys.
Some generated output still needs the same review you would give code from a teammate. If a Go or Kotlin file places an import below a declaration after you choose a single-file or big-number setup, move the import to the top of the file or switch to the safer multi-file layout before compiling. For Java, trust the files you actually receive in the download rather than assuming a one-file layout.