Favicon of JSON Schema

JSON Schema

JSON Schema is the vocabulary for describing, validating, and documenting JSON data — the third schema type every major schema registry supports alongside Avro and Protocol Buffers, and the one that requires no new encoding on the wire.

LicenseOpen source (permissive)· BSD-3-Clause
DeploymentSelf-hostedManaged
PricingFree
Operational complexityLow
WorkloadInteractiveStreaming

Use it when

  • Payloads must stay human-readable: events cross organizational boundaries, get debugged by people, or must be consumable by anything that parses JSON.
  • The registry slot needs filling without a new encoding; Confluent, Karapace, Glue, and Apicurio all take it beside Avro and protobuf.
  • Contracts need expressiveness: patterns, ranges, oneOf and conditional shapes, a constraint vocabulary no binary format matches.
  • The schemas already exist; OpenAPI 3.1 and AsyncAPI contracts are JSON Schema documents underneath.

Think twice when

  • Bytes and parse cost matter; text JSON with a second validation pass is the most expensive option in this capability.
  • Evolution must be governed: the specification defines no compatibility rules, so the rules are the registry's, and additionalProperties decides whether adding a field is even forward compatible.
  • Draft fragmentation will bite: 2020-12 is current, but AWS Glue validates drafts 04, 06, and 07, so "we use JSON Schema" must always say which draft.
  • Strong types are the point; 1 is just a number, and timestamps are strings by convention.

How it runs

Nothing runs: it is a JSON document describing which JSON documents are acceptable, validated by libraries in every language. A schema names its dialect with $schema, registries apply their own compatibility policies, and code generation, where wanted, comes from third-party tools each supporting its own subset.

Details

Compare

How JSON Schema answers the questions Serialization Formats turns on.

Serialization Formats
How it works
EncodingNone, and the honest answer is that this row is not an encoding at all. The bytes on the wire are ordinary JSON text; JSON Schema is a separate JSON document that says which of those texts are acceptable. It adds no framing, no tags, no length prefixes and no compaction, and a validated payload is byte-identical to an unvalidated one. Every other row here answers how values become bytes; this one answers which documents are allowed, which is why it sits oddly in the comparison, and why the comparison still needs it, because it is what the ecosystem actually uses when the payload is JSON
Random accessNone, and a step worse than the parsing formats rather than merely absent. JSON is text, so a reader tokenises from the first byte with no offsets, no lengths and no index anywhere in the document, and numbers arrive as decimal strings that must be converted rather than read. The schema changes none of that and adds to it: validation is a second walk over the parsed values. Where Cap'n Proto reads a field by computing an offset and Thrift at least skips by type tag, this row parses everything and then checks it
Self-describingThe most self-describing payload in the capability and the least typed, which is the trade the whole format rests on. Every field carries its name in the bytes, so a JSON document can be read, logged and understood with no schema anywhere, the exact opposite of Avro, whose datum is undecodable without one. What the payload cannot say is what anything means: 1 is a number rather than an int32, a timestamp is a string by convention, and precision is whatever the parser chose. The schema supplies that missing half and describes itself while doing it, naming its dialect with $schema and its resolution base with $id, so a contract states which version of the rules it expects to be read under
Schema evolutionThe specification says nothing about it, which is the single largest gap between this row and Avro's. There are no field numbers, no ordinals, no writer-and-reader resolution algorithm (only the required keyword and whatever conventions a team adopts. Compatibility is therefore delegated, and Confluent's documentation says so outright) "JSON Schema does not explicitly define compatibility rules", before supplying its own: a lenient or strict policy crossed with an open or closed content model, where the model is decided by whether additionalProperties is set. That setting is the whole game. Leave it open and optional fields can be added or removed within the usual backward and forward rules; set it to false and the schema forbids unknown members, so adding an optional field is backward compatible but no longer forward compatible. The rules a team works under are the registry's, not the specification's
Type systemSix instance types (null, boolean, object, array, number and string, with integer as a number carrying no fractional part) and then by a wide margin the largest constraint vocabulary in the capability. Validation keywords cover numbers (multipleOf, minimum and maximum with exclusive forms), strings (minLength, maxLength, pattern), arrays (uniqueItems, minContains, maxContains) and objects (required, dependentRequired, minProperties); applicators compose whole schemas with allOf, anyOf, oneOf, not and if/then/else; metadata keywords carry title, description, default, deprecated and readOnly; content keywords describe strings holding encoded data. format is the subtle one, by default an annotation rather than an assertion, with implementations required to keep validation of it off unless the format-assertion vocabulary is declared. No other row here can express "a string matching this pattern" or "exactly one of these shapes" at all
RPCNone, and the absence is structural rather than a missing feature: this row describes documents, so anything that carries them sits above it. What it does have is the position underneath the API description layer (OpenAPI 3.1's Schema Object is a superset of JSON Schema 2020-12, and AsyncAPI's is a superset of Draft 07) so a very large share of the world's HTTP and event API contracts are JSON Schema documents wrapped in something that defines the calls, and the two biggest consumers sit on different drafts. Cap'n Proto builds RPC into the format; this one is built into the formats that describe RPC
Spec versionsThe most complicated answer on this page, and the reason this key exists. The current release is 2020-12 and has been for nearly six years, while drafts 04, 06 and 07 remain in production use, AWS Glue validates against those three rather than the current one. The project's own account is candid about how it got here: it left the IETF process because the word "draft" was reading as unfinished when the format was already everywhere, then found restarting its own release train harder than expected, with the January 2025 post admitting four years without a release, promising the next one is "getting really close", and naming upgrade compatibility as "our #1 concern" alongside an x- convention for extension keywords and a proposal stage so features are implemented before they are frozen. Then in July 2026 the direction reversed again: an IETF working group is being chartered, initially proposing 2020-12 with the Core, Validation and Hyper-Schema documents combined, on a dual track beside independent releases
Adoption and maturityUbiquitous and under-resourced at the same time, which no other row here manages. It is the schema language of OpenAPI 3.1 and AsyncAPI, of package.json and editor settings and Kubernetes manifests, of every Kafka registry that is not Protobuf-only, and now of LLM structured output, and that last one comes with the qualification the project publishes itself, that constrained-generation tools "support only a subset of the specification or fall back to post-generation validation", with uniqueItems, dependentRequired and if/else not supported at generation time anywhere. Governance is an OpenJS Foundation At-Large project since January 2022, with maintainers who were employed by Postman to work on it, and a specification repository carrying about 5,100 stars and 452 forks. The story of this row is the distance between how much depends on it and how much of it anything actually implements
Connections
Registry supportUniversal among the Kafka registries and one of the three names that appear everywhere: Confluent, Karapace and AWS Glue take it beside Avro and Protobuf, Apicurio takes it among nine artifact types, and only Buf, which is Protobuf and nothing else, does not. The detail worth carrying is the one this catalog already records for Glue, JSON Schema validated at drafts 04, 06 and 07 through the Everit library. A major registry pinned three drafts behind the current release is the fragmentation problem stated as a product decision rather than as a complaint
Generated codeNever required and never standardised, and the direction usually runs backwards. The specification defines validation, not binding, so there is no official compiler and no reference generator; what exists is a large third-party layer (quicktype, json-schema-to-typescript, datamodel-code-generator and their peers) each supporting its own subset of the vocabulary. Just as often the schema is the output rather than the input, generated from types already annotated in code. Against Thrift, where the compiler is the product, and Avro, where generation is a convenience over dynamic reading, this row has no canonical answer at all

Share:

Alternatives to JSON Schema

Favicon

 

  
  
Favicon

 

  
  
Favicon