JSON to JSON Schema

Infer a JSON Schema (draft-07) from a sample — a key is required only when every object has it, mixed slots become anyOf, and nothing the sample cannot prove (formats, enums, bounds) is invented. Free, no sign-up — runs locally in your browser.

Your work is auto-saved in this browser only, so a refresh won't lose it. Nothing is uploaded.

Why infer a schema from a sample?

Schemas usually exist on paper long after the API that needed them started shipping — or never exist at all. Yet the payload itself is a precise witness: every key it carries, every type, every field that only sometimes shows up. This generator cross-examines that witness and writes the draft-07 schema it testifies to. The result is a working skeleton for the jobs schemas actually do — validating responses in tests, driving editor completion, documenting a contract, checking a partner's payload before it poisons yours — which you then tighten with domain knowledge the sample cannot contain (formats, ranges, enums).

How to use this tool

  1. Paste the most representative JSON you have. For an array payload, paste the whole array: the generator merges all elements, so optional fields are learned from absence, not guessed.
  2. Optionally give the schema a title; it lands in the title keyword and makes the file self-describing in repositories and registries.
  3. Press Generate schema, then copy or download schema.json.
  4. Validate the schema against fresh samples with your usual validator before trusting it in CI — inference is only as complete as the examples.
  5. Refine deliberately: add format, enum, numeric bounds and additionalProperties decisions where your domain knowledge outranks the sample's evidence.

The inference rules

Objects become type: "object" with a schema per property; required lists the keys present in every sighting at that position. Arrays merge all elements into one items schema; an empty array yields an unconstrained items rather than a fabricated type. Numbers split into integer and number by observed fraction. Mixtures — a slot that held different kinds across the sample — become an anyOf of exactly the observed kinds, null included when it appeared. And the generator never emits what no sample can prove: no formats, no patterns, no enums, no additionalProperties: false.

Worked example

Given a two-element product list where the second item has no tag list:

[
  { "id": 1, "price": 9.99, "tags": ["new"] },
  { "id": 2, "price": 12 }
]

the inferred schema keeps tags out of required and widens price to number:

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

Frequently asked questions

What does "required" mean in the generated schema?

A property is listed in required only if it appears in every object the generator saw at that position. Show it one object and everything is required; show it an array of a hundred objects and the required list is the intersection — the keys no real example ever omits. That is the honest limit of inference: the schema describes the data you showed it, and a field your API guarantees but your sample happens to skip cannot be invented. Feed the generator your most complete, most varied sample and the required lists get correspondingly truthful.

Why did a property become anyOf with several types?

Because the sample showed that slot holding more than one kind of value — say, an integer in most elements and a string in one, or null in some and an object in others. The schema reports that mixture faithfully as an anyOf of the observed branches instead of picking a winner. If the mixture is actually dirty data (an ID that arrived as a string once), the anyOf is doing you a favour: it points at exactly the inconsistency worth cleaning up at the source.

How are integer and number distinguished?

Standard JSON Schema semantics: a slot is integer only if every number observed there is whole; a single fractional value makes it number (which integers also satisfy, so the schema stays correct). One subtlety worth knowing: JSON cannot write 1.0 differently from 1 in any way a parser preserves, so a field that is always sent as whole values infers as integer even if the producer considers it a float. The reverse mistake cannot happen — a real fraction forces number automatically.

Why is there no format, pattern or enum in the output?

Deliberately. A string that looks like an email or a date in your sample is still just a string as far as the evidence goes; stamping format: "date-time" on it would make validators reject values the schema has no business rejecting, and an enum built from a sample of three values would forbid the fourth legitimate one. This generator emits only what the sample proves: types, required keys, array items, observed shape. Adding formats, ranges and enums is the refinement step you do with knowledge of the domain — it takes seconds per field once the skeleton exists.

Which schema draft is generated, and will my validator accept it?

JSON Schema draft-07, identified by the $schema line at the top — the most widely supported draft across validators, editor tooling, OpenAPI 3.0 workflows and form generators. The generator does not emit additionalProperties: false, so the schema accepts fields your sample did not show. That permissiveness is a choice, not an oversight: a schema inferred from examples that forbade everything unobserved would reject the next legitimate response your API produces.

Related tools