Back to Blog
11 min read
Guide

JSON to TypeScript, Zod & Go Struct Online — Generate Types from JSON

Free JSON to TypeScript, Zod schema, and Go struct generator online. Paste JSON, merge arrays into optional fields and unions, and copy typed code—runs in your browser.

By Spoold Editorial TeamReviewed for tool accuracy
Editorial Policy

Stop hand-typing API response types.

Need a JSON to TypeScript, JSON to Zod, or JSON to Go struct converter? Spoold's JSON → Types reads your payload, merges every array element, and generates typed code in one paste—entirely in your browser.

Open the JSON to types generator →

Why generate types from JSON?

Every integration starts the same way: you curl an endpoint, stare at a large response, and write types by hand. It is tedious, and the types drift the moment the API changes. Generating a first draft from a real payload gets you 90% of the way in seconds, leaving you to refine names, enums, and edge cases.

TypeScript

Compile-time safety for API clients, fixtures, and config. Interfaces or type aliases, with optional readonly.

Zod

Runtime validation for untrusted data, with the static type inferred from the same schema via z.infer.

Go

Structs with json tags, exported field names, and pointers for optional values.

One input, three outputs

Start with this JSON:

{
  "id": 7,
  "name": "Ada",
  "tags": ["admin", "beta"],
  "address": { "city": "London", "zip": null },
  "orders": [
    { "sku": "A1", "qty": 2 },
    { "sku": "B2", "qty": 1, "gift": true }
  ]
}

TypeScript output:

export interface Root {
  id: number;
  name: string;
  tags: string[];
  address: Address;
  orders: Order[];
}

export interface Order {
  sku: string;
  qty: number;
  gift?: boolean;
}

export interface Address {
  city: string;
  zip: null;
}

Zod (excerpt) — note .int() for whole numbers and .optional() for the key missing from the first order:

export const OrderSchema = z.object({
  sku: z.string(),
  qty: z.number().int(),
  gift: z.boolean().optional(),
});
export type Order = z.infer<typeof OrderSchema>;

Go (excerpt) — optional values become pointers with omitempty:

type Order struct {
	Sku  string `json:"sku"`
	Qty  int    `json:"qty"`
	Gift *bool  `json:"gift,omitempty"`
}

How the inference works

  • Arrays are merged. The generator compares every element, not just the first. A key present in only some objects becomes optional.
  • Mixed types become unions. A field that is a string in one element and a number in another becomes string | number.
  • Null becomes nullable. If a field is sometimes null, you get T | null, .nullable(), or *T.
  • Integers and floats are distinguished. 5 and 5.5 widen to a float; all-whole numbers stay int in Go and Zod.
  • Names come from keys. orders becomes Order for its items; identical shapes share one type.

Tip: feed it several examples

If your sample is a single object, the tool cannot know which fields are sometimes missing. Wrap two or three representative payloads in an array and optional fields are detected automatically.

Options worth knowing

  • Root name — name the top-level type (User, ApiResponse).
  • As observed / All optional — mark everything optional for PATCH bodies or partial updates.
  • Readonly — readonly properties and arrays in TS, .readonly() in Zod.
  • interface vs type — pick your house style.
  • z.infer type — emit the inferred type next to each schema.

TypeScript types vs Zod schemas

TypeScript types exist only at compile time. If a server returns something unexpected, your app still compiles and then fails at runtime. A Zod schema checks the real value when you call parse or safeParse, so use it at trust boundaries: HTTP responses, webhooks, form submissions, environment variables, and local storage. Use plain interfaces for internal data that never crosses a boundary.

Go struct tips

  • Field names are exported and use Go initialisms (ID, URL) while the json tag keeps the original key.
  • Pointer fields distinguish “missing” from “zero value” in encoding/json.
  • Change int to int64 or strings to time.Time where your domain needs it.
  • Ambiguous or mixed values become any; narrow them after you inspect real data.

Python and Rust

Python can emit a Pydantic BaseModel or a dataclass. Optional fields use T | None = None and are ordered after required fields so a dataclass stays valid. Rust emits serde structs: JSON keys that are not snake_case get rename, missing keys become Option, and integers are i64.

Workflow on Spoold

  1. Open /tools/json/to-types.
  2. Paste JSON (use Format to pretty-print) and choose TypeScript, Zod, Python, Go, or Rust.
  3. Set the root name and options with the chips.
  4. Copy the output. The conversion is saved to History so you can reload it later, and Share creates a link.
  5. Need a particular value first? Find it with the JSONPath Tester, then generate types for just that sub-document.

Pitfalls

  • Empty arrays carry no element information and become unknown[].
  • Dictionary-like objects (IDs as keys) generate one property per key; replace them with Record<string, T> or z.record().
  • Sample bias — types describe your sample, not your business rules. Add enums, brands, and format checks yourself.
  • Large numeric IDs can exceed JavaScript's safe integer range; model them as strings.

Related guides

Related search terms

json to typescriptjson to interfacejson to zodzod schema from jsonjson to go structgo struct json tagstypescript interface generatorgenerate types from jsonquicktype alternativez.infer

Frequently asked questions

Is the JSON to types generator free?
Yes—client-side, no sign-up. Your JSON stays in your browser.
Does it handle nested objects and arrays?
Yes. Nested objects become separate named types, and arrays are merged across all elements so optional fields and unions are detected.
Interface or type alias?
Both are available. Interfaces suit object shapes and declaration merging; type aliases are convenient for unions and mapped types.
Why use Zod instead of just TypeScript types?
Types are erased at runtime. Zod validates actual data and infers the type from the schema, so you maintain one definition.
Why are some Go fields pointers?
Optional or nullable fields become pointers with omitempty so you can tell a missing value from a zero value.
Can it convert a top-level array?
Yes. A root array becomes an alias like type Root = RootItem[] with an item type generated from the merged elements.
Can I mark everything optional?
Yes. Choose All optional for partial updates or when your sample is not exhaustive.

Try It Now

Put this guide into practice with our free tools. No sign-up required.

Open JSON → Types