Dev.to WebDev 🛠 Dev 👁 0 📖 3 min read

Stop hand-writing JSON Schemas: infer them from your sample payloads, in the browser

Hand-writing a JSON Schema from an API response is tedious, error-prone work. The more fields a payload has, the easier it is to forget a required entry or mistype a field. And the schema you write by hand is only as goo

Hand-writing a JSON Schema from an API response is tedious, error-prone work. The more fields a payload has, the easier it is to forget a required entry or mistype a field. And the schema you write by hand is only as good as the sample you stared at while writing it.

There is a faster first draft: paste sample payloads into an inference tool and let it generate the schema. I tried ToolsByUs's JSON Schema Generator — it infers a Draft 2020-12 schema from your samples and validates documents against it on the spot, all in the browser. Your sample data never leaves the tab, because the whole thing runs client-side.

The sample I ran through it

[
  {"id": 1, "name": "taro", "email": "[email protected]", "status": "active", "created_at": "2026-11-01T09:00:00Z"},
  {"id": 2, "name": "hana", "email": "[email protected]", "status": "inactive", "created_at": "2026-11-02T10:30:00Z", "nickname": "h"}
]

What the inference actually gets right — and one thing it doesn't

  • required detection: only properties present in every sample become required. Here id, name, email, status and created_at are required; nickname appears in only one of the two samples, so it stays optional. That is exactly the rule you would apply by hand, applied without fail.
  • format detection: email is inferred as format: email and created_at as format: date-time. UUIDs and URIs are detected the same way.
  • The enum surprise: strings with few distinct values can become enums — but not always. The default threshold is 4, yet when I ran this sample, status stayed a plain {"type": "string"} despite having only two values, active and inactive. No enum was generated. So a small value set does not guarantee an enum; check the output rather than assuming.
  • Type widening: when the same key holds an integer in one sample and a string in another, the inferred type widens to ["integer", "string"] instead of silently picking one.

Validate without leaving the page

The round-trip validator below the generator takes a test payload and checks it against the generated schema in real time, showing which path and keyword failed on a violation. That kills the usual loop of writing a schema, opening a second tool to validate it, going back to fix it, and re-validating. One page does both halves.

Honest caveats

  • Inference only sees the samples you give it. A field that happens to be present in every sample is treated as required even if it is optional in reality. If a field is optional, include a sample where it is missing and it drops out of required.
  • The inferred schema is a starting point, not a finished contract. Read it before shipping it — especially the required list and any format it guessed.
  • If all you need is TypeScript types, the same site's JSON-to-TypeScript converter is the better tool. A schema is the artefact you want when several languages need runtime validation against the same contract.
  • Client-side means your machine does the work and your data stays local. For very large payloads that can be slower than a server — but for the hand-sized samples you actually infer schemas from, it is instant.

If you have API samples lying around, the first draft of your schema takes seconds. Spend the saved time on the part that matters: checking whether the inferred schema matches what your API actually promises.

Try it: https://toolsbyus.com/json-schema-generator

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.