json

FormatValidateConvert

JSON to TypeScript

JSON
Language
Structured output

Result· read-only

—TypeScript

The result appears here.

Generate

Generate code from JSON, YAML, XML or CSV.

Your document never leaves the browser.

Types in ten languages from JSON, YAML, XML or CSV — generated in your browser, never uploaded.

Choose what the source is and which language you want, then paste a document. The types are written while you type, from every record in it, and the JSON they were inferred from sits one tab away.

10

languages from one inference

3

structured-output schemas: OpenAI, Claude, Gemini

0

bytes leave your machine

Ten languages, one inference

The picker offers TypeScript, Python, JSON Schema, Java and C# as tabs, and More holds Go, Zod, Rust, Kotlin and Swift. All ten read one inferred model of the data, so a field missing from some records is optional in every language at once, and a nested object gets its own named type in each of them.

This is the generator behind Generate in the editor, not a copy of it. The same document gives the same code here and there, and a language option set on one page is already set on the other.

1

Two users, one of them without an email

[
  { "id": 1, "name": "Ada", "email": "[email protected]" },
  { "id": 2, "name": "Alan" }
]
2

TypeScript

export interface RootItem {
  id: number;
  name: string;
  email?: string;
}

export type Root = RootItem[];
3

Go, from the same inference

package main

type RootItem struct {
	ID    int64   `json:"id"`
	Name  string  `json:"name"`
	Email *string `json:"email,omitempty"`
}

type Root []RootItem

Why the JSON step is on screen

Code is never generated from YAML, XML or a spreadsheet directly. Each is first read into JSON by the reader Convert uses, and the types are inferred from that JSON. When the source is not JSON, the row says so — From, then JSON, then the language — and the result gains a JSON tab beside the code.

Showing the step matters because reading decides the types. A CSV cell written as 42 becomes a number and one written in quotes stays a string; an XML element holding 42 is a string unless number detection is on. When a type looks wrong, the JSON tab shows which reading produced it, and it can be copied, downloaded or opened in the editor.

1

CSV, with From set to CSV and the language TypeScript

sku,qty,code
PEN-01,2,"42"
INK-07,1,"07"
2

The JSON tab, the step the types are inferred from

[
  {
    "sku": "PEN-01",
    "qty": 2,
    "code": "42"
  },
  {
    "sku": "INK-07",
    "qty": 1,
    "code": "07"
  }
]
3

The TypeScript, written from that JSON

export interface RootItem {
  sku: string;
  qty: number;
  code: string;
}

export type Root = RootItem[];

Options in two groups

1

XML, with From set to XML and the language TypeScript

<order>
  <id>7</id>
  <item>pen</item>
</order>
2

With Always make arrays for: item, and Detect numbers and booleans on

export interface Order {
  id: number;
  item: string[];
}

export interface Root {
  order: Order;
}

Option

Read XML

Read XML: which elements always become arrays, even when one appears only once, and whether numbers and booleans are detected in text.

Option

Read CSV or TSV

Read CSV or TSV: the delimiter, guessed or chosen, and whether the first row holds the column names.

Option

The language

The language: TypeScript’s interface or type alias and its optional-field spelling, Python’s Pydantic, dataclass or TypedDict style, the package for Java and Go, the namespace for C#, and the rest, each under its own name.

Structured output for OpenAI, Claude and Gemini

Beside Language, a second row named Structured output offers OpenAI, Claude and Gemini. Each writes the schema that provider’s API takes for structured output, so the model answers in the shape of your sample rather than in free text. Output chooses between the bare schema and a request fragment to merge into the body of your own call.

OpenAI’s fragment fits the Responses API or Chat Completions, Claude’s is either JSON output or a strict tool, and Gemini’s fits generateContent or the Interactions API. The API and Use controls, and a name where the request carries one, appear only while Output is Request fragment, since the bare schema has no use for them.

A provider schema is stricter than the JSON Schema target, so a few things change to fit. OpenAI wants every property listed as required, so a field missing from some records stays required and accepts null instead. For OpenAI and Claude, a root that is not an object, such as a list of records, is wrapped as a required property named items. A record, an object used as a map from ids to values, becomes for those two a list of key and value pairs whose values are JSON text, to be parsed back after the answer arrives.

The list under the schema says which of these changes happened, and at which path, and warns when a provider limit is near: Claude’s 24 optional properties, for one, or OpenAI’s ten levels of nesting. Nothing on this page calls a provider. The schema is written in the tab, and you send it with your own key from your own code.

1

A list of two users, one of them without an email

[
  { "id": 1, "name": "Ada", "email": "[email protected]" },
  { "id": 2, "name": "Linus" }
]
2

OpenAI’s schema for it. The list is wrapped as items, and email is required but may be null

{
  "type": "object",
  "properties": {
    "items": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/RootItem"
      }
    }
  },
  "required": [
    "items"
  ],
  "additionalProperties": false,
  "$defs": {
    "RootItem": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string"
        },
        "email": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "id",
        "name",
        "email"
      ],
      "additionalProperties": false
    }
  }
}

Only the editor can do this part

Generating from one branch of a large response, rather than the whole of it, needs a tree to pick the branch from. Open the JSON in the editor, choose a node in the Tree view, and Generate proposes a type name from its path.

Nothing is sent anywhere

Reading, inference and code generation all happen in this tab. Payloads full of customer records can be turned into types without leaving the machine, and with the connection off the page carries on working once it has loaded.

FAQ

Frequently asked questions

Didn’t find your answer?Write to us on the contact page →
Can I generate types from a YAML config file?

Yes. Set From to YAML, or paste the whole file and let the page recognise it. The YAML is read as YAML 1.2, so yes and no stay strings, and the code is generated from the JSON it becomes.

Why is a CSV column typed as a string when it holds numbers?

Because at least one cell in it was quoted or held text. The JSON tab shows each cell as it was read, which is the quickest way to find the one that made the column a string.

Can I use the OpenAI schema with another provider?

Mistral, Groq, xAI and other OpenAI-compatible APIs take the Chat Completions request shape, so choose Chat Completions under API. Each of them documents which schema keywords it honours, and that list is worth reading before relying on a particular one.

Does it remember my source?

For this browser tab only. A reload keeps the document and the language; a new tab opens on JSON and TypeScript with an empty source.

Keyboard shortcuts

Send feedback

Questions, bug reports and feature requests are all welcome. A bug report is easiest to act on with the shape of the document that caused it — never send anything confidential.

Email us

Contact page, in a new tab, so this page stays as it is.

Settings

Indent

The result is written with it — YAML and XML at 2 spaces when it is Tab.

Code text size
14 px

Both panes.

Wrap long lines

Load from a URL

Your browser fetches it directly — the request goes to that site, never to us.