JSON Schema Generator

Paste a JSON sample and instantly generate a matching JSON Schema (draft-07) with inferred types, required properties, and array item schemas. A free online tool from Staaarter, right in your browser.

Runs locallyUpdated 2026-07-18

Overview

Introduction

Writing a JSON Schema by hand is precise but slow, especially for deeply nested payloads. This tool infers a complete draft-07 schema directly from a real JSON sample, giving you a solid starting point you can refine.

The appeal is speed over precision: a hand-written schema for a payload with a dozen nested fields means typing out a properties map, a required array, and type keywords for every one of them, then keeping it in sync as the payload evolves. Generating it from an actual sample instead takes the structure you already have and turns it into schema syntax mechanically, which is faster and less error-prone than transcribing it by eye.

What Is JSON Schema Generator?

A JSON Schema generator inspects a sample JSON value and produces a JSON Schema document describing its types, required properties, and nested structure, in a format that runtime validators like Ajv or frameworks like OpenAPI can consume.

The output targets draft-07 specifically, identified by the $schema value http://json-schema.org/draft-07/schema#, since that draft has the widest support across validators and tooling. It includes type inference down to the integer-vs-number distinction, a required array of every observed key, and optionally an examples array embedding the sample's actual values.

Because generation is a pure, local transformation, running the same sample through it twice always produces the identical schema, and nothing about your sample, its shape, its field names, or its actual values, is sent anywhere to produce that output. That matters here specifically because a useful generated schema depends on a genuinely representative sample, which in practice often means pointing this tool at a real API response or production config rather than a synthetic placeholder.

How JSON Schema Generator Works

The generator walks the sample recursively: objects become `type: object` schemas with a `properties` map and a `required` array listing every observed key; arrays become `type: array` schemas with an `items` schema inferred from their elements (merged via `anyOf` when elements have different shapes); primitives map to `string`, `number`, `integer`, `boolean`, or `null` based on their JavaScript type and value.

Array item schemas are deduplicated before being combined, which is what keeps a uniform array (every element the same shape) from producing a redundant repeated union. The signature used for that comparison is coarser than it might look, though. It's based on each item schema's own top-level keys, type/properties/required/additionalProperties for an object, just type for a primitive, not on the property names inside an object or the specific primitive value type. In practice that means anyOf only shows up when array items differ at the level of a whole JSON category (an object mixed with a primitive, say), not when two objects simply have different properties or two primitives have different types; those cases silently collapse to whichever item's schema was seen first. See the FAQ for a worked example of when this does and doesn't produce the anyOf you might expect.

When To Use JSON Schema Generator

Use it right after capturing a real API response or config sample, when you need a validation schema for a JSON payload and don't want to write draft-07 syntax by hand, or as a first draft to hand-refine into a stricter schema with format validators, min/max constraints, or enums.

It's also a fast way to document a payload's shape for other consumers: pasting a sample response and copying the generated schema into API documentation or an OpenAPI spec is quicker than describing the fields in prose, and the result is something a validator can actually enforce.

Features

Advantages

  • Produces a valid, ready-to-use draft-07 schema directly from real data.
  • Distinguishes integers from floating point numbers.
  • Handles arrays with mixed-shape items using anyOf.
  • Optional example embedding documents the schema with real sample values.

Limitations

  • Requires the input to be well-formed JSON, since comments and trailing commas aren't supported.
  • Inferred from a single sample, so it can't detect constraints like min/max, string formats (email, uri), or enums without manual editing.
  • Every observed property is marked required by default since a single sample provides no evidence of optionality.

JSON Schema vs. TypeScript Interfaces

JSON Schema vs. TypeScript Interfaces
JSON Schema (this tool)TypeScript interfaces
Validates data at runtimeYes, with a validator like AjvNo, types disappear at compile time
Works outside a TypeScript projectYesNo
Consumed by OpenAPI and API gatewaysYesNo, needs a conversion step
Best forValidating incoming API payloadsCompile-time safety inside your own code

Examples

Simple object

Input

{"id":1,"name":"Ada","active":true}

Output

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "name": { "type": "string" },
    "active": { "type": "boolean" }
  },
  "required": ["id", "name", "active"],
  "additionalProperties": false
}

Each property gets an inferred type, and all observed keys become required.

Array of uniform-shape objects

Input

{"users":[{"id":1,"name":"Ada"},{"id":2,"name":"Grace"}]}

Output

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "users": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" }
        },
        "required": ["id", "name"],
        "additionalProperties": false
      }
    }
  },
  "required": ["users"],
  "additionalProperties": false
}

Every element of the users array has the same shape, so the deduper collapses them into a single items schema instead of repeating it per element or wrapping it in an unnecessary anyOf.

Nested object with a schema title and embedded examples

Input

{"user":{"id":1,"email":"ada@example.com"}}

Output

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "User",
  "type": "object",
  "properties": {
    "user": {
      "type": "object",
      "properties": {
        "id": { "type": "integer", "examples": [1] },
        "email": { "type": "string", "examples": ["ada@example.com"] }
      },
      "required": ["id", "email"],
      "additionalProperties": false,
      "examples": [{ "id": 1, "email": "ada@example.com" }]
    }
  },
  "required": ["user"],
  "additionalProperties": false,
  "examples": [{ "user": { "id": 1, "email": "ada@example.com" } }]
}

With the 'Schema title' field set to User and 'Include examples' enabled, the title appears once at the document root, and an examples array embedding the actual sample value is added at every level, the object, and each individual primitive.

Array of mixed-shape objects doesn't produce a full anyOf

Input

{"items":[{"id":1,"name":"Ada"},{"id":2,"price":9.99}]}

Output

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" }
        },
        "required": ["id", "name"],
        "additionalProperties": false
      }
    }
  },
  "required": ["items"],
  "additionalProperties": false
}

The two items have entirely different properties (name vs. price), but both produce an object schema with the same top-level shape, so the second item's schema is discarded as a 'duplicate' and only the first item's shape (id, name) survives. The price field is silently absent from the schema entirely; this array needs a hand-written anyOf to actually capture both shapes.

Mixing an object and a primitive does trigger anyOf

Input

{"items":[1,{"a":1}]}

Output

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "items": {
      "type": "array",
      "items": {
        "anyOf": [
          { "type": "integer" },
          {
            "type": "object",
            "properties": { "a": { "type": "integer" } },
            "required": ["a"],
            "additionalProperties": false
          }
        ]
      }
    }
  },
  "required": ["items"],
  "additionalProperties": false
}

Unlike two differently-shaped objects, an integer and an object produce dedup signatures with different top-level keys (just type vs. type/properties/required/additionalProperties), so they count as genuinely different shapes and a real anyOf is generated.

Empty array has no items schema

Input

{"tags":[]}

Output

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "tags": { "type": "array" }
  },
  "required": ["tags"],
  "additionalProperties": false
}

With no elements to inspect, the generator can't infer an item type, so tags gets type: array with no items keyword at all, rather than a guessed or empty items schema. A validator will accept any array here, including one holding any type of element.

Best Practices & Notes

Best Practices

  • Treat the generated schema as a first draft, and add format validators, min/max bounds, and enums by hand for anything user-facing.
  • If some fields are genuinely optional, remove them from the 'required' array after generation, or generate from a sample that omits them.
  • Set additionalProperties to true if you expect the payload to evolve with new fields you don't want to reject.
  • Don't assume a mixed-shape array will automatically produce a full anyOf; inspect the items schema after generating, and if your array has objects with genuinely different properties or a mix of primitive types, build the anyOf by hand from schemas generated for each shape separately.
  • When a numeric field could plausibly hold a decimal even if your sample only shows whole numbers (a price, a percentage, a rating), change its inferred 'integer' to 'number' by hand, since JSON parses 10.0 and 10 identically and the generator can't tell them apart.
  • Regenerate whenever the upstream payload shape changes meaningfully, rather than hand-patching an old schema indefinitely, so the schema doesn't drift from what the API or config actually produces.

Developer Notes

Array item schemas are deduplicated before being combined with anyOf, but the signature used for that comparison is each item schema's own top-level key set (type/properties/required/additionalProperties for an object, just type for a primitive), not the property names nested inside an object or a primitive's actual value type. That's a coarser check than 'structurally identical': two objects with completely different properties produce the same top-level signature and get treated as duplicates, so only the first is kept, and an anyOf only actually appears when array items differ at the level of a whole JSON category (for example, an object mixed with a primitive). Type inference for numbers uses Number.isInteger() on the parsed value, so it can't distinguish a JSON literal written as 10 from one written as 10.0; both parse to the identical JavaScript number and are typed as 'integer' either way.

JSON Schema Generator Use Cases

  • Bootstrapping a validation schema for an API request or response body
  • Documenting the expected shape of a JSON payload for API consumers
  • Generating a schema to plug into OpenAPI or Ajv-based validation middleware
  • Creating a contract test schema from a real production sample
  • Producing a machine-checkable contract to attach to a pull request when an API response shape changes, so reviewers and CI can see and enforce exactly what changed
  • Quickly documenting the shape of a webhook payload for integration partners without hand-writing JSON Schema syntax

Common Mistakes

  • Shipping the generated schema unmodified when the API truly has optional fields: review and adjust the required array.
  • Expecting string format validation (email, date-time, uri) to be inferred automatically. It isn't, since JSON alone can't signal intended format.
  • Generating from an unrepresentative sample and missing fields that only appear in some responses.
  • Assuming a heterogeneous array of objects will produce a full anyOf listing every shape observed; in practice, differently-shaped objects are usually deduplicated down to just the first one seen, so the items schema needs manual review for any array that isn't uniform.
  • Forgetting that additionalProperties: false is set at every object level by default, which will reject any real payload field that wasn't present in the specific sample you generated from, including fields added later.
  • Trusting a number's inferred 'integer' type to mean the field can never hold a decimal, when it only reflects that the sample's value happened to be a whole number; JSON has no separate literal syntax for 10 versus 10.0.

Tips

  • Generate from your richest, most complete sample response to capture the most fields.
  • Pair with the JSON to TypeScript tool when you need both compile-time types and runtime validation from the same sample.
  • Toggle 'Include examples' on when you want the schema to double as documentation, and off when you want the smallest possible schema file or when the sample contains anything sensitive.
  • After generating, search the output for 'anyOf' to see exactly which arrays the generator considered heterogeneous; its absence in an array you expected to be mixed is a sign the shapes collapsed into one and need a manual fix.

References

Frequently Asked Questions