NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1617 most downloaded on PyPI
A high-performance JSON Schema validator for Python
Last release 2 days ago
02 Oct 2026
Ships fairly regularly
a new release about every 9 days
Nearly every release is documented
notes for 60 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
6 years old
137 releases · first in 2020
One column per quarter.
canonicalize keeping a reference to a cycle of bare references under not or oneOf instead of treating it as accepting every value.
canonicalize keeping a reference to a cycle of bare references under not or oneOf instead of treating it as accepting every value.Validator::draft returning the default draft instead of the one $schema declares.
Validator::draft returning the default draft instead of the one $schema declares.unevaluatedProperties and unevaluatedItems beside a $recursiveRef ignoring what the reference target evaluates.unevaluatedProperties ignoring the configured regex engine and its limits for patternProperties.schemaLocation of keywords a $ref JSON Pointer reaches through a subschema with its own $id.type, minItems and maxItems ignored beside items when the applicator vocabulary is disabled.schemaLocation of keywords inside a nested $id resource counting from the document root.required beside properties ignored when the applicator vocabulary is disabled, and required, minContains and maxContains applied when the validation vocabulary is disabled.type errors in a type-only items subschema pointing at items instead of the failing element's type.patternProperties annotations missing its JSON Pointer fragment.type: array beside schema-form items omitting passing type, minItems and maxItems units and nesting failing ones under items.schemaLocation and absolute keyword location of $ref, $dynamicRef and $recursiveRef nodes not pointing at the reference target.schemaLocation URIs not percent-encoding their fragment, such as a space in a property name.false, missing its JSON Pointer fragment.required, minContains and maxContains errors pointing at a sibling keyword.$ref siblings in Draft 4, 6 and 7 schemas.additionalItems messages counting allowed items instead of extra ones, and "1 items" in masked unevaluatedItems messages.$dynamicRef and $recursiveRef resolving in the dynamic scope of another path to the same schema, depending on property order.unevaluatedProperties and unevaluatedItems ignoring what then or else evaluates when if is true or false.$ref chains.format: "regex" and meta-schema validation rejecting escaped punctuation such as \- in patterns.patternProperties regex reporting the subschema instead of the pattern and its location.Keywords of a subschema declaring a Draft 2019-09+ $schema under a Draft 4, 6 or 7 root being ignored.
$schema under a Draft 4, 6 or 7 root being ignored.$schema being checked against the root's meta-schema.$dynamicRef targets in another document resolving relative references and reporting absolute keyword locations against the referencing document.
$dynamicRef targets in another document resolving relative references and reporting absolute keyword locations against the referencing document.$ref to an $anchor or fragment $id validating against another anchor in the same document. #1668schema_path of errors under a $ref or $dynamicRef to a named schema pointing at the resource root instead of that schema.uri and uri-reference formats check the syntax directly instead of parsing each value into a URI.
uri and uri-reference formats check the syntax directly instead of parsing each value into a URI.Pyo3 validators when an Enum member's value override emptied a list or dict holding the instance being read.uri and uri-reference formats check the syntax directly instead of parsing each value into a URI.Enum members read their stored value directly instead of calling the value property in Pyo3 validators.canonical.json.to_string on free-threaded Python when another thread resized a list or dict. #1664Enum member's value override, a custom keyword or a custom format emptied a list or dict holding the instance being read, during validation, schema conversion or canonical.json.to_string.uri and uri-reference formats check the syntax directly instead of parsing each value into a URI.Enum members read their stored value directly instead of calling the value property.oneOf and anyOf whose branches each require a property fixed to a distinct string validate only the branch matching the instance's value.
oneOf and anyOf whose branches each require a property fixed to a distinct string validate only the branch matching the instance's value.meta.is_valid and meta.validate check a schema against the bundled drafts without converting it first, about 2x faster on the benchmarked schemas.find_unsatisfiable missing a oneOf over $ref branches beside a sibling none of them admits.oneOf and anyOf whose branches each require a property fixed to a distinct string validate only the branch matching the instance's value.Meta.valid? and Meta.validate! check a schema against the bundled drafts without converting it first, 2 to 5x faster on the benchmarked schemas.Canonical.find_unsatisfiable missing a oneOf over $ref branches beside a sibling none of them admits.type: null failing validation silently (it should raise TypeError).backend = Pyo3 on #[jsonschema::validator], generating a validator that reads Python objects in place.backend = Magnus on #[jsonschema::validator], generating a validator that reads Ruby objects in place.jsonschema::meta::pyo3, the bundled meta-schema validators for a schema held as a Python object.jsonschema::meta::magnus, the bundled meta-schema validators for a schema held as a Ruby object.methods = { ... } on #[jsonschema::validator], selecting which of is_valid, validate, and iter_errors are generated.json::Jsonb, validating a Postgres jsonb value in place, behind the jsonb feature.oneOf and anyOf whose branches each require a property fixed to a distinct string validate only the branch matching the instance's value.validate checks required in the same pass over an object as properties, instead of looking up each required name.oneOf over $ref branches beside a sibling none of them admits, which canonicalized to an allOf instead of false.multipleOf incorrectly accepted 1e-400 and other magnitudes below the smallest f64 subnormal with arbitrary-precision (they are not zero).f64 without arbitrary-precision.Fixed Packaging issue.
canonical.RawReason , what stopped a run from modeling a document, and RawView.reason and RawView.pointer , carrying it beside the subschema the run s
canonical.RawReason, what stopped a run from modeling a document, and RawView.reason and RawView.pointer, carrying it beside the subschema the run stopped on.oneOf whose branches share a region too wide to expand, which spent the document's whole intersection allowance on that choice and kept the document Raw.canonical::RawReason, what stopped a run from modeling a document, and canonical::RawView, carrying it beside the document and a pointer to the subschema the run stopped on.ValidationOptions::is_known_format, whether a format of that name is checked under a draft.canonical::CanonicalView::Raw carries a canonical::RawView in place of the document alone.oneOf whose branches share a region too wide to expand, which spent the document's whole intersection allowance on that choice and kept the document Raw.Canonicalization of an anyOf over an allOf through a $ref to a union, which left that union nested inside the outer one.
anyOf over an allOf through a $ref to a union, which left that union nested inside the outer one.anyOf whose branch narrowing runs out of intersections, which left true as a branch inside the union.canonical.PatternValueFailsView , which ObjectView.violations records for a patternProperties entry.
canonical.PatternValueFailsView, which ObjectView.violations records for a patternProperties entry.not over patternProperties, which kept the entry under not instead of recording the demand a key breaks.anyOf over objects sharing a properties key under patternProperties, which settled only on a second pass.not over an allOf folded through a reference, which settled only on a second pass.multipleOf divisor past f64 precision, which was not taken to divide itself.anyOf over a value beside a window pinned to it, which settled only on a second pass.minProperties: 1 beside a not that already demands a key, which settled only on a second pass.canonical::ObjectViolationView gained the PatternValueFails variant, which negation records for a patternProperties entry.not over patternProperties, which kept the entry under not instead of recording the demand a key breaks.unevaluated* beside a conditional reaching no key or index the node already evaluates, which spent a case on it.Raw.anyOf over objects sharing a properties key under patternProperties, which settled only on a second pass.not over an allOf folded through a reference, which settled only on a second pass.multipleOf divisor past f64 precision, which was not taken to divide itself.anyOf over a value beside a window pinned to it, which settled only on a second pass.minProperties: 1 beside a not that already demands a key, which settled only on a second pass.backend = SerdeJson on #[jsonschema::validator] , generating a validator that reads serde_json::Value .
backend = SerdeJson on #[jsonschema::validator], generating a validator that reads serde_json::Value.PreparedDocument::unsatisfiable_pointers, listing every subschema no value satisfies.unevaluated* beside dependentSchemas or if/then/else, which kept the document Raw.not over patternProperties, which kept the document Raw.validate and iter_errors check each assertion keyword with the is_valid path and build an error only for a failing one.evaluate holds its output tree in one allocation instead of one per node.pattern of ^\S*$ scans bytes instead of decoding every character.validate on properties beside a two-name required confirms both names in the pass that checks the properties, instead of looking each up first.enum compares an option's length and first and last eight bytes before its full text.~ and / eight bytes at a time before it is copied.type: array with items and minItems/maxItems checking the built-in length bound even when a custom keyword overrides minItems or maxItems, so the bound was evaluated twice.type, required or maxLength not replacing the built-in check for that keyword.items, minLength, properties or additionalProperties leaving its sibling keywords unchecked.#[jsonschema::validator] generated code that named serde_json directly, so it needed the consumer crate to depend on serde_json too.not over an object with properties, patternProperties and additionalProperties, which applied additionalProperties to the keys listed in properties.Draft 4 type: integer matching a float or not depending on its repr ; a float is never a draft 4 integer.
type: integer matching a float or not depending on its repr; a float is never a draft 4 integer.type: integer accepting Decimal("1E+2").uniqueItems accepting 0 alongside -0.0 in arrays of more than 15 items.allOf of object schemas walks their property maps once instead of looking every key up.properties and required compare short names without memcmp.type: integer, and type sets containing it, are up to 67x faster on float-heavy instances.type: integer is up to 20x faster on float-heavy instances.ValidationError is up to 38% faster.evaluate is up to 30% faster, from rendering each node's locations once.$ref target once instead of per reference site.$id encodes each absolute location once instead of re-validating it.enum listing strings or integers, with or without null, matches against a set instead of comparing each candidate.type: integer matching a Float or not depending on its formatting; a Float is never a draft 4 integer.uniqueItems accepting 0 alongside -0.0 in arrays of more than 15 items.allOf of object schemas walks their property maps once instead of looking every key up.properties and required compare short names without memcmp.type: integer is up to 6x faster on float-heavy instances.evaluate renders each node's locations once instead of rebuilding them.$ref target once instead of per reference site.$id encodes each absolute location once instead of re-validating it.enum listing strings or integers, with or without null, matches against a set instead of comparing each candidate.Location::segments, iterating the segments without collecting them.CanonicalizeOptions::prepare, canonicalizing any number of a document's subschemas by JSON Pointer, with the document indexed once.--at POINTER flag of jsonschema canonicalize, canonicalizing only the subschema at that pointer without breaking its references into the rest of the document.jsonschema canonicalize reads YAML schemas (.yaml/.yml) as well as JSON.canonical::{ArrayView, IntegerView, NumberView, ObjectView, StringView, TypedGroupView}, the payload types of CanonicalView, so consumers can name them in signatures.jsonschema-value failing to build with default-features = false.jsonschema-value failing to build for wasm32-unknown-unknown, which needs getrandom's wasm_js backend.type: integer accepting numbers written with an exponent, like 1e2.type: integer answering differently for the same number across representations.uniqueItems accepting 0 alongside -0.0 in arrays of more than 15 items.allOf of object schemas walks their property maps once instead of looking every key up.properties and required compare short names without memcmp.$ref target once.$id is up to 15% faster, from encoding each absolute location once.required scans small objects once instead of looking up each key.enum listing strings or integers, with or without null, matches against a set instead of comparing each candidate.evaluate is up to 33% faster, from rendering each node's locations once.type: integer with arbitrary-precision no longer allocates a string per number.type: integer, and type sets containing it, are up to 54x faster on float-heavy instances with arbitrary-precision.type: integer is up to 20x faster for the Pyo3 and Magnus representations.multipleOf rejecting valid values like 1070468.14 for 0.01 without arbitrary-precision .
multipleOf rejecting valid values like 1070468.14 for 0.01 without arbitrary-precision.minLength and maxLength together now scan the string once.multipleOf with a fractional divisor is 8-16x faster.unevaluatedProperties is up to 2.9x faster.evaluate is up to 27% faster on reference-heavy schemas.The offline: keyword argument, refusing to fetch references outside registry: .
offline: keyword argument, refusing to fetch references outside registry:.patternProperties $ref matches a key properties names.draft: keyword argument and the Draft201909Validator / Draft202012Validator classes gating keywords on the vocabularies of the $schema they override, so the validator accepted every instance.valid? disagreeing with validate!, each_error, and evaluate on a schema that reaches its own $ref twice, one of them under not.offline argument, refusing to fetch references outside registry.patternProperties $ref matches a key properties names.ValidationError.absolute_keyword_location.draft argument and the Draft201909Validator / Draft202012Validator classes gating keywords on the vocabularies of the $schema they override, so the validator accepted every instance.is_valid disagreeing with validate, iter_errors, and evaluate on a schema that reaches its own $ref twice, one of them under not.Evaluation::is_valid.Location::is_empty.Display for ErrorEntry.ValidationOptions::offline and canonical::CanonicalizeOptions::offline, refusing to fetch references outside the registry.idna Cargo feature, enabled by default, gating the idn-hostname and idn-email formats. #1313--offline flag of jsonschema validate, jsonschema bundle and jsonschema dereference.ValidationErrors' Display gained the instance path of each error.default-features = false, the idn-hostname and idn-email formats now require the new idna feature. Without it they are unknown formats, which are accepted by default, or rejected at build time under should_ignore_unknown_formats(false). Add idna to the feature list to keep the previous behavior.patternProperties $ref matches a key properties names.is_valid disagreeing with validate, iter_errors, and evaluate on a schema that reaches its own $ref twice, one of them under not.format: email and format: idn-email rejecting an empty quoted string as the local part (it should be accepted).format: email and format: idn-email rejecting an address literal whose IPv6: tag is not written in that exact case (the tag is case-insensitive).format: email accepting a non-ASCII character in the local part (it should be rejected).ValidationOptions::with_draft gating keywords on the vocabularies of the $schema it overrides, so the validator accepted every instance.iter_errors collects into a single buffer instead of allocating and re-boxing an iterator at every schema node.ValidationOptions::with_vocabulary and the vocabularies attribute on jsonschema::validator , declaring support for a vocabulary this crate does not im
ValidationOptions::with_vocabulary and the vocabularies attribute on jsonschema::validator, declaring support for a vocabulary this crate does not implement.--vocabulary flag of jsonschema validate.Vocabulary gained the FormatAssertion variant, which its Draft 2020-12 URI parses to instead of Vocabulary::Custom, and is marked non_exhaustive.uniqueItems length ceiling not reading an items or contains schema written as a $ref.format rejects.format accepted under a meta-schema requiring the Format-Assertion vocabulary (it should be rejected).true read as an annotation, so a meta-schema requiring it accepted values its format rejects.https://json-schema.org/draft/2020-12/meta/format-assertion meta-schema not declaring its vocabulary, so a schema written against it annotated format instead of asserting it.$id keeping its $vocabulary unread, so a schema written against it got every Draft 2020-12 vocabulary.$schema rejected as an unknown meta-schema (it should build).regex format reading the Rust regex dialect (it should read the ECMA-262 dialect in Unicode mode).uri-template format rejecting an apostrophe in a literal (it should accept it, per RFC 6570 errata 6937).duration format accepting weeks combined with a time part, such as P1WT1H (it should reject it).unevaluatedProperties or unevaluatedItems beside a $ref that cycles back to the node, written as #, through its $id, or through a chain of definitions.unevaluatedProperties or unevaluatedItems over a deep allOf or $ref chain costs its depth instead of its square.CanonicalSchema::satisfiability answers Yes for a string whose pattern or format a matching value can be built from.
CanonicalSchema::satisfiability answers Yes for a string whose pattern or format a matching value can be built from.CanonicalSchema::satisfiability answers No where a format takes no string of the length the schema asks for.CanonicalSchema::negate taking apart a union that reads a definition through its own if, so a schema and its negation shared a value.CanonicalSchema::subtract dropping a Draft 4 array member an element demand partly takes.CanonicalSchema::covers answering Yes where a Draft 4 element demand refuses a member.maxLength is 0 keeping a pattern, format, or content facet unread, so the same constraints written in one object and written as an allOf reached different canonical forms.not over a wide object schema costs its branch count instead of its square.not over an object schema is linear in its property count, not quadratic.not over an object schema with additionalProperties: false no longer costs cubic time in its property count.CanonicalSchema::union and CanonicalSchema::subtract .
CanonicalSchema::union and CanonicalSchema::subtract.CanonicalizationError::UnsupportedResult, reported where the canonical form does not support a set operation's result.OperandMismatch::DocumentRoots, reported where both operands read # and it names a different document on each side.jsonschema validate -i INSTANCE without a SCHEMA argument validates each instance against the schema named in its own $schema property. #1470CanonicalSchema::is_satisfiable is now CanonicalSchema::satisfiability, answering Yes, No, or Unknown - Yes wherever a value can be exhibited, not only for the forms listing their members.CanonicalSchema::covers decides through the difference as well: No where the argument keeps values the receiver rejects, Yes where nothing is left over.CanonicalSchema::is_subset_of is now CanonicalSchema::covers, answering Yes, No, or Unknown for whether the receiver admits every value the argument admits.CanonicalSchema::negate returns Result rather than Option.CanonicalizationError::UnmodeledOperand is now CanonicalizationError::UnsupportedOperand, and means only that an operand is a Raw pass-through.$ref folds through the body it names, so canonicalizing a document and combining its parts with the set operations reach one form; a document holding a reference cycle keeps the form it had.$ref to # at the combined result instead of the document it was written in, including one named by a definition the result keeps.$ref whose target is true or false, which panicked.CanonicalSchema::covers answering Unknown for a schema against itself, where that schema is a $ref.CanonicalSchema::union keeping a $ref beside the schema it names, where the other three operations read through it.CanonicalSchema::covers and CanonicalSchema::subtract cancelling two nodes written the same way whose # names a different document.additionalProperties reaching a key the pattern map matches when a finite key constraint closes the map, which dropped values both operands accept.$defs entry read past a wider schema written out at every use, rather than kept as the pointer it was.$ref as a pointer instead of reading through it, so a schema written with a $ref did not cancel against the same schema written out.CanonicalSchema::subtract asking for a complement where the difference is one of the operands or empty, declining on schemas it can subtract.$defs entries the result no longer references, which then showed up in the emitted schema.CanonicalSchema::union declining over an approximated intersection, where the union itself is exact.$id contains one. #1473unevaluatedProperties and unevaluatedItems ignoring an $id on a subschema they walk through, so a relative $ref inside it resolved against the enclosing resource.CanonicalSchema#union and CanonicalSchema#subtract.JSONSchema::Canonical::UnsupportedResult, raised where the canonical form does not support a set operation's result.JSONSchema::Canonical::IncompatibleOperands where both operands read # and it names a different document on each side.JSONSchema::Canonical::Containment, Satisfiability, Distinctness and Kind: named constants for the symbols covers, satisfiability, kind and ArrayView#distinctness return, each with an ALL list.CanonicalSchema#satisfiable? is now CanonicalSchema#satisfiability, answering :yes, :no, or :unknown - :yes wherever a value can be exhibited, not only for the forms listing their members.CanonicalSchema#covers decides through the difference as well: :no where the argument keeps values the receiver rejects, :yes where nothing is left over.CanonicalSchema#is_subset_of is now CanonicalSchema#covers, answering :yes, :no, or :unknown for whether the receiver admits every value the argument admits.CanonicalSchema#negate raises where it used to return nil.JSONSchema::Canonical::UnmodeledOperand is now JSONSchema::Canonical::UnsupportedOperand, and means only that an operand is a Raw pass-through.$ref to # at the combined result instead of the document it was written in, including one named by a definition the result keeps.$ref whose target is true or false, which crashed the interpreter.CanonicalSchema#covers answering :unknown for a schema against itself, where that schema is a $ref.CanonicalSchema#union keeping a $ref beside the schema it names, where the other three operations read through it.CanonicalSchema#covers and CanonicalSchema#subtract cancelling two nodes written the same way whose # names a different document.additionalProperties reaching a key the pattern map matches when a finite key constraint closes the map, which dropped values both operands accept.$defs entry read past a wider schema written out at every use, rather than kept as the pointer it was.$ref as a pointer instead of reading through it, so a schema written with a $ref did not cancel against the same schema written out.CanonicalSchema#subtract asking for a complement where the difference is one of the operands or empty, declining on schemas it can subtract.$defs entries the result no longer references, which then showed up in the emitted schema.CanonicalSchema#union declining over an approximated intersection, where the union itself is exact.CanonicalSchema.union and CanonicalSchema.subtract.canonical.UnsupportedResult, raised where the canonical form does not support a set operation's result.canonical.IncompatibleOperands where both operands read # and it names a different document on each side.canonical.Containment, canonical.Satisfiability, canonical.Distinctness and canonical.CanonicalKind: the possible answers of covers(), satisfiability(), kind and ArrayView.distinctness.CanonicalSchema.is_satisfiable() is now CanonicalSchema.satisfiability(), answering with the canonical.Satisfiability members YES, NO or UNKNOWN - YES wherever a value can be exhibited, not only for the forms listing their members.CanonicalSchema.covers() decides through the difference as well: NO where the argument keeps values the receiver rejects, YES where nothing is left over.CanonicalSchema.is_subset_of() is now CanonicalSchema.covers(), answering with the canonical.Containment members YES, NO or UNKNOWN for whether the receiver admits every value the argument admits.CanonicalSchema.kind and ArrayView.distinctness answer with the canonical.CanonicalKind and canonical.Distinctness members instead of strings.CanonicalSchema.negate() raises where it used to return None.canonical.UnmodeledOperand is now canonical.UnsupportedOperand, and means only that an operand is a Raw pass-through.$ref to # at the combined result instead of the document it was written in, including one named by a definition the result keeps.$ref whose target is true or false, which crashed the interpreter.CanonicalSchema.covers() answering UNKNOWN for a schema against itself, where that schema is a $ref.CanonicalSchema.union() keeping a $ref beside the schema it names, where the other three operations read through it.CanonicalSchema.covers() and CanonicalSchema.subtract() cancelling two nodes written the same way whose # names a different document.additionalProperties reaching a key the pattern map matches when a finite key constraint closes the map, which dropped values both operands accept.$defs entry read past a wider schema written out at every use, rather than kept as the pointer it was.$ref as a pointer instead of reading through it, so a schema written with a $ref did not cancel against the same schema written out.CanonicalSchema.subtract() asking for a complement where the difference is one of the operands or empty, declining on schemas it can subtract.$defs entries the result no longer references, which then showed up in the emitted schema.CanonicalSchema.union() declining over an approximated intersection, where the union itself is exact.Canonicalization of a oneOf whose branches name object targets a required constant tells apart, which degrades to a union.
oneOf whose branches name object targets a required constant tells apart, which degrades to a union.CanonicalSchema::to_json_schema on a definition emits only the definitions that one names, not the whole document's.Up to 380x faster canonicalization of a oneOf whose overlapping branches carry many properties, which no longer removes shared regions the exactly-one
oneOf whose overlapping branches carry many properties, which no longer removes shared regions the exactly-one spelling discards.http://json-schema.org/schema meta-schema URI as a custom dialect, where it names the current draft.patternProperties entry matching every key leaving additionalProperties: false spelled as a key constraint, where it forbids nothing.oneOf whose overlapping branches carry many properties, which no longer removes shared regions the exactly-one spelling discards.http://json-schema.org/schema meta-schema URI as a custom dialect, where it names the current draft.patternProperties entry matching every key leaving additionalProperties: false spelled as a key constraint, where it forbids nothing.unevaluatedProperties/unevaluatedItems set to true forcing the whole document to stay unmodeled beside an unresolved applicator, where the keyword rejects nothing regardless of the evaluated set.unevaluatedProperties/unevaluatedItems beside a $ref forcing the whole document to stay unmodeled, where the reference's own evaluated properties or items are known once it is resolved.CanonicalizeOptions::with_retriever to fetch external resources absent from the registry.
CanonicalizeOptions::with_retriever to fetch external resources absent from the registry.CanonicalizeOptions::with_base_uri to resolve relative references in the root schema.oneOf whose branches name disjoint targets, which degrades to a union.patternProperties entry beside schema-valued additionalProperties, where matching keys escape its value constraint.CanonicalSchema::definition resolving # to the document the handle was read against.not over a union of many branches.$defs references, which avoid decoding unescaped definition names.oneOf whose many branches overlap.true and false subschemas repeatedly.CanonicalSchema::definition and CanonicalSchema::definitions handing out a target that names the document root without that document, where # points at the target instead.items tail beyond an array's length ceiling surviving canonicalization, where it governs no element.CanonicalSchema::to_json_schema leaving the document root out of a node emitted below it, where # points at that node instead.Canonicalization of a negated uniqueItems, where the complement demands a repeated element under the length floor two elements imply.
uniqueItems, where the complement demands a repeated element under the length floor two elements imply.contains demands sharing no value, where their counts add up into a length floor.CanonicalSchema::negate through references, where the complement of the resolved target takes the reference's place.propertyNames and additionalProperties, where the complement spells the violating-key demand instead of a not residual.additionalProperties under Draft 4, where the violating-key demand spells the closed property map.not a reference, where the complement of the resolved target takes the pointer's place.oneOf, where the complement spells the values no branch admits beside the values two branches share.items under Draft 4, where the violating-element demand spells the barred element schema.ArrayView reports distinctness in three states, so an array demanding a repeated element reads apart from one demanding distinct elements.CanonicalSchema::negate keeping a root self-reference in the complement, where it points at the complement instead of the source.additionalItems that tails no tuple keeping the whole document unmodeled under Draft 2020-12.Canonicalization of not an integer schema under Draft 4, which the number leaf carries as barred integers.
not an integer schema under Draft 4, which the number leaf carries as barred integers.not a multipleOf, which numeric leaves carry as barred divisors.not an integer schema, where a barred divisor of one spells the non-integer numbers.not a pattern, which string leaves carry as barred patterns.not a typed value set under Draft 4, such as {"type": "integer", "enum": [1, 2]}.CanonicalSchema::is_subset_of, whether the other schema admits every value this one admits.CanonicalSchema::is_subset_of failing to prove a union of array branches a subset of itself.CanonicalSchema::intersect admitting values one side rejects when its additionalProperties governs the keys the other side's patternProperties match.multipleOf schema collapsing to the empty set when f64 rounds its bounds together.arbitrary-precision when the fraction exceeds the expansion cap.multipleOf comparing values through a lossy f64 conversion under arbitrary-precision, such as 1e-400 passing {"maximum": 0}.Canonicalization of not a string format, which the string leaf carries as barred formats.
not a string format, which the string leaf carries as barred formats.not an existential demand, which an array fails exactly when no element matches.not a string value set, which the string leaf carries as excluded values.unevaluatedItems beside contains, where the elements it matches are evaluated and the tail admits either.unevaluated* beside anyOf or oneOf, where every branch evaluating the same keys or indexes pins what is left over.not an array element schema, which an array fails exactly when one element violates it.CanonicalSchema::intersect, the values both schemas admit.CanonicalSchema::negate, the values a schema rejects.CanonicalSchema::definition, one reference target by URI.i64 admitted by a fractional bound f64 rounds it onto, such as -10000000000000000000000000 under {"maximum": -10000000000000000000000000.1}.2^53 admitted by a bound f64 rounds onto it, such as 9007199254740992 under {"minimum": 9007199254740993}.contains subschema beside both minContains and maxContains overwriting a sibling keyword of the same name, such as items.CanonicalSchema hashing and equality cost the node instead of the whole document.Canonicalization of a recursive schema with no finite witness, which now folds to false.
false.$dynamicRef and $recursiveRef, which resolve through the dynamic scope and stay symbolic like any other reference. A dangling $dynamicRef errors rather than staying Raw.minContains under uniqueItems, where a demand asking for more matches than its own schema has distinct values now folds to false.patternProperties coverage closed by additionalProperties: false, spelled as the closed map it was parsed from.oneOf whose branches repeat, where a repeated branch can never contribute exactly one match.$ref whose target is an empty schema, which now folds to false.unevaluatedItems beside allOf, where every branch must pass and so the indexes they evaluate are known without the instance.unevaluatedProperties beside allOf, where every branch must pass and so what they evaluate is known without the instance.type list holding integer beside other types with enum, which previously modeled only when spelled as an allOf.patternProperties patterns matching finitely many keys, such as ^a$ and ^(a|b)$.unevaluatedProperties and unevaluatedItems when no in-place applicator sits beside them.additionalItems values that are not schemas silently ignored beside an array-form items (they should fail the build like additionalProperties).additionalItems beside a boolean items rejecting every instance, such as {"additionalItems": false, "items": false}.additionalItems beside a non-array items value failing schema compilation with an error blaming additionalItems (the keyword should be ignored).2^64, such as {"maxItems": 18446744073709551616}.f64 range admitted by a fractional bound it exceeds, such as 1e400 under {"exclusiveMaximum": 0.1}.$ref at the root of an $id-bearing subresource dropped as a self-reference when its pointer matched the one that reached that subresource.unevaluatedItems counting prefixItems as evaluating elements before Draft 2020-12, where it is not a keyword.evaluate by building each location in a single allocation instead of two, reusing the instance location a node already built, and caching evaluation paths across instance nodes.Faster serialization of canonicalized schemas.
multipleOf beside numeric bounds far from zero.float can hold are exposed as decimal.Decimal instead of a rounded, wider bound.canonicalize for multipleOf beside numeric bounds far from zero.jsonschema-value: Ruby builds on x64-mingw-ucrt.
jsonschema-value: Ruby builds on x64-mingw-ucrt.canonicalize rejecting pattern_options (it should take the same regex configuration as validators).Generic JSON input: options_for builds a validator over any instance representation implementing json::Json, so instances validate without conversion
options_for builds a validator over any instance representation implementing json::Json, so instances validate without conversion to serde_json::Value. #239meta::validate_for and meta::is_valid_for for checking a schema document held in any representation implementing json::Json against its meta-schema.jsonschema::canonicalize. It reduces a reasonable subset of JSON Schemas to their normal forms.multipleOf incorrectly accepted integers past u64 that are not multiples of the divisor.jsonschema::canonicalize. It reduces a reasonable subset of JSON Schemas to their normal forms.multipleOf incorrectly accepted integers past u64 that are not multiples of the divisor.list subclasses incorrectly rejected as unsupported types.value resolves back to the member.serde_json. #239meta.is_valid / meta.validate by working on Python objects directly instead of converting them to serde_json.### Fixed - Packaging issue again.
properties validators.{"type": "array", "items": {...}} schemas.Faster validator compilation by pre-sizing internal caches.
canonical.json.to_string incorrectly keeping the input spelling of fractional Decimal values (e.g. Decimal("1.50") and Decimal("1.5") producing different strings).canonical.json.to_string incorrectly emitting exponent form for small floats (e.g. 1e-7 instead of 0.0000001).Missing required errors in evaluate() output for schemas with properties and a two-entry required array. #1220
required errors in evaluate() output for schemas with properties and a two-entry required array. #1220contentEncoding errors for invalid UTF-8 after decoding incorrectly had empty instance_path and schema_path.#[jsonschema::validator] (~5% across benchmarked schemas), via aliasing repeated paths in the emitted code.iter_errors for #[jsonschema::validator]-generated validators.
iter_errors for #[jsonschema::validator]-generated validators.anyOf and oneOf validation errors, matching runtime validators.$recursiveRef in generated validators incorrectly resolved to the innermost $recursiveAnchor (it should resolve to the outermost one).i64/u64 range incorrectly compared against numeric bounds through lossy f64 rounding under arbitrary-precision (e.g. {"minimum": -9223372036854775808} accepted -9223372036854775809).canonical::json::to_string under arbitrary-precision ("1e-2" becomes "0.01", "1.50" becomes "1.5") and correctly-rounded float parsing (serde_json's float_roundtrip).multipleOf validation for integer instances with integer divisors, via integer arithmetic instead of floating-point modulo.meta.is_valid and meta.validate incorrectly accepted some Draft 2019-09 schemas that the meta-schema rejects.i64/u64 range incorrectly compared against numeric bounds through lossy f64 rounding (e.g. {"minimum": -9223372036854775808} accepted -9223372036854775809).multipleOf validation for integer instances with integer divisors, via integer arithmetic instead of floating-point modulo.Keyword::iter_errors for reporting multiple validation errors from a single custom keyword. #1071
#[jsonschema::validator] attribute macro (behind the macros feature) that compiles a JSON Schema into is_valid and validate implementations at build time.Keyword::iter_errors for reporting multiple validation errors from a single custom keyword. #10711.85.0.macros feature, via compile-time meta-schema validators.type under items asserted with the Validation vocabulary disabled.$ref targets without their own $schema (e.g. $defs entries).3.15t).iter_errors(instance) method on custom keyword validators for reporting multiple errors from a single keyword. #1071pyo3 to 0.29.type under items asserted with the Validation vocabulary disabled.$ref targets without their own $schema (e.g. $defs entries).pyo3 update.Stack overflow with a self-referential $dynamicRef combined with unevaluatedProperties or unevaluatedItems.
$dynamicRef combined with unevaluatedProperties or unevaluatedItems.unevaluatedProperties and unevaluatedItems results when a meta-schema disables the Applicator vocabulary.multipleOf incorrectly rounds integer instances above 2^53 to f64 before the divisibility check on builds without the arbitrary-precision feature.
multipleOf incorrectly rounds integer instances above 2^53 to f64 before the divisibility check on builds without the arbitrary-precision feature.idn-email format rejected non-ASCII characters in quoted local parts (e.g. "δοκιμή"@example.com).
idn-email format rejected non-ASCII characters in quoted local parts (e.g. "δοκιμή"@example.com).idn-hostname format accepted A-labels that decode to a disallowed code point (e.g. xn--7a).
idn-hostname format accepted A-labels that decode to a disallowed code point (e.g. xn--7a).IntoRegistryResource for Arc . #1129
prefixItems incorrectly recognised as a known keyword in Draft 2019-09 and earlier (it is 2020-12 only).pattern validation errors displayed the internally translated regex instead of the original schema pattern. #1149registry is passed.Percent-encoded characters in $ref URI fragments (e.g. #/$defs/Request%20class) are now decoded when stored as schema_path.
$ref URI fragments (e.g. #/$defs/Request%20class) are now decoded when stored as schema_path.Panic in the regex engine when matching against patterns with very large {0,N} quantifiers.
{0,N} quantifiers.Memory not reclaimed when a Validator for a schema with recursive $ref or $dynamicRef is dropped. #1125
Validator for a schema with recursive $ref or $dynamicRef is dropped. #1125wasm32-wasip1 and wasm32-unknown-emscripten targets.required not enforced when additionalProperties is a schema object and required lists exactly 2 keys.
required not enforced when additionalProperties is a schema object and required lists exactly 2 keys.required not enforced when properties has 15 or more entries and required lists exactly 2 keys.
required not enforced when properties has 15 or more entries and required lists exactly 2 keys.ValidatorMap for validating instances against subschemas identified by URI-fragment JSON pointer. #1075
ValidatorMap for validating instances against subschemas identified by URI-fragment JSON pointer. #1075-i/--instance (e.g. jsonschema validate schema.json -i *.json). #1085dereference function to recursively inline $ref references. #422jsonschema dereference subcommand to dereference a schema from the command line.with_registry now borrows the prepared registry. ValidationOptions::with_resource and ValidationOptions::with_resources were removed in favor of building a Registry first. See the Migration Guide for the details.validator_cls_for.Resolver and Resolved types for programmatic schema resolution.dereference function to recursively inline $ref references. #422ValidatorMap for validating instances against subschemas identified by URI-fragment JSON pointer. #1075wasm32 targets. #1093Incorrect handling of multipleOf validation for negative numeric instances.
multipleOf validation for negative numeric instances.duration format when hours and seconds appear without minutes, or years and days without months.CLI: jsonschema validate and jsonschema bundle subcommands. Flat invocation (jsonschema schema.json -i …) is deprecated — use jsonschema validate inst…
bundle(schema) / async_bundle(schema) / ValidationOptions::bundle: produce a Compound Schema Document with external $ref targets embedded in a draft-appropriate container (definitions for Draft 4/6/7, $defs for Draft 2019-09/2020-12) while preserving $ref values. #791.jsonschema validate and jsonschema bundle subcommands. Flat invocation (jsonschema schema.json -i …) is deprecated — use jsonschema validate instead. #791.ValidationError::absolute_keyword_location() to get the absolute keyword location URI of the schema node that produced the error. #737.ValidationError::into_parts() now returns ValidationErrorParts instead of a tuple.bundle(schema, ...): produce a Compound Schema Document with all external $ref targets embedded in a draft-appropriate container (definitions for Draft 4/6/7, $defs for Draft 2019-09/2020-12; Appendix B). #791.ValidationError.absolute_keyword_location to get the absolute keyword location URI of the schema node that produced the error.hostname format now applies legacy RFC 1034 semantics in Draft 4/6 and keeps IDNA A-label validation in Draft 7+.
hostname format now applies legacy RFC 1034 semantics in Draft 4/6 and keeps IDNA A-label validation in Draft 7+.canonical::to_string(value) for canonical JSON serialization (stable key ordering and numeric normalization), useful for deduplicating equivalent JSON
canonical::json::to_string(value) for canonical JSON serialization (stable key ordering and numeric normalization), useful for deduplicating equivalent JSON Schemas.contentMediaType, contentEncoding, and contentSchema keywords.canonical.json.to_string(object) for canonical JSON serialization (stable key ordering and numeric normalization), useful for deduplicating equivalent JSON Schemas.contentMediaType, contentEncoding, and contentSchema keywords.str enums whose value lookup raises an exception.value lookup raises an exception.Optimize pattern and patternProperties for ^(a|b|c)$ alternations via linear array scan.
pattern and patternProperties for ^(a|b|c)$ alternations via linear array scan.^\S*$ patterns by replacing regex with a direct ECMA-262 whitespace check.anyOf, format, unevaluatedProperties, and unevaluatedItems now correctly collect annotations per spec.validator_cls_for(schema) function to detect and return the appropriate validator class for a schema.anyOf, format, unevaluatedProperties, and unevaluatedItems now correctly collect annotations per spec.pattern and patternProperties for ^(a|b|c)$ alternations via linear array scan.^\S*$ patterns by replacing regex with a direct ECMA-262 whitespace check.SWAR digit parser accepted bytes :–? (0x3A–0x3F) as valid digits during date, time, and date-time format validation, potentially allowing malformed va
:–? (0x3A–0x3F) as valid digits during date, time, and date-time format validation, potentially allowing malformed values to pass.pattern prefix optimization to handle escaped slashes (^\/) and exact-match patterns (^\$ref$).enum for cases when all variants are strings.:–? (0x3A–0x3F) as valid digits during date, time, and date-time format validation, potentially allowing malformed values to pass.ValidationError via __cause__, preserving the original exception type and message.pattern prefix optimization to handle escaped slashes (^\/) and exact-match patterns (^\$ref$).enum for cases when all variants are strings.Reduce dynamic dispatch overhead for non-recursive $ref resolution.
$ref resolution.format: "regex" validation.$ref resolution.format: "regex" validation.rust-toolchain.toml from wheels. #1012JsonType::as_str method for zero-allocation type name access.
JsonType::as_str method for zero-allocation type name access.ValidationErrorKind::keyword is now public.tls-ring feature flag to opt into using ring as the TLS crypto provider instead of the default aws-lc-rs. #997.yaml/.yml) instance files in text output mode. #988aws-lc-rs. Users who need ring can opt in via the tls-ring feature flag. This resolves potential conflicts with other libraries using aws-lc-rs. #997$ref targets that resolve to boolean schemas.OnceLock to avoid repeated formatting during evaluate().$ref targets that resolve to boolean schemas.PyList_New + PyList_SetItem for array conversion to avoid reallocations.ValidationError, ReferencingError, and decimal.Decimal types to avoid repeated module imports.evaluate().as_str instead of to_string for type names in validation errors to avoid allocations.Replace regex-based uri-template format validation with a hand-rolled RFC 6570 parser.
uri-template format validation with a hand-rolled RFC 6570 parser.items keyword for simple type schemas ({"type": "string"}, {"type": "number"}, etc.) to eliminate dynamic dispatch overhead.unevaluatedProperties validation via O(1) property lookup and short-circuit oneOf evaluation.pyo3 to 0.28.pythonize dependency.uri-template format validation with a hand-rolled RFC 6570 parser.items keyword for simple type schemas ({"type": "string"}, {"type": "number"}, etc.) to eliminate dynamic dispatch overhead.unevaluatedProperties validation via O(1) property lookup and short-circuit oneOf evaluation.Pre-built wheels for free-threaded Python (3.13t, 3.14t) on Linux, macOS, and Windows.
Pre-built wheels for musllinux (Alpine Linux) on x86_64 and aarch64.
musllinux (Alpine Linux) on x86_64 and aarch64.Exclude internal tracker field from ValidationError Debug output.
tracker field from ValidationError Debug output.aws-lc-rs to ring to simplify building from source on some Linux distributions. #957type: integer validation in Draft 4 now correctly accepts large integers outside the i64/u64 range when arbitrary-precision feature is enabled.aws-lc-rs to ring to fix import errors when building from source on some Linux distributions. #957Draft4Validator now correctly validates large Python integers outside the i64/u64 range (e.g., -9223372036854775809, 18446744073709551616) as valid for type: integer.ValidationErrorKind::Custom now includes a keyword field containing the custom keyword name.
ValidationErrorKind::Custom now includes a keyword field containing the custom keyword name.patternProperties for simple prefix patterns (e.g., ^x-).ValidationErrorKind.name property returning the keyword name (e.g., "minimum", "divisibleBy").ValidationErrorKind.value property returning the constraint value.ValidationErrorKind.as_dict() method returning error details as a dictionary.patternProperties for simple prefix patterns (e.g., ^x-).HttpOptions and ValidationOptions::with_http_options() for configuring HTTP client behavior (timeouts, TLS verification, custom CA certificates) when
HttpOptions and ValidationOptions::with_http_options() for configuring HTTP client behavior (timeouts, TLS verification, custom CA certificates) when fetching external schemas.--timeout, --connect-timeout, --insecure, and --cacert flags for HTTP configuration.keywords parameter for extending JSON Schema with domain-specific validation rules.HttpOptions for configuring HTTP client behavior (timeouts, TLS verification, custom CA certificates) when fetching external schemas.ValidationError::evaluation_path() for the dynamic path including $ref traversals.
ValidationError::evaluation_path() for the dynamic path including $ref traversals.Keyword::validate no longer receives path parameters, and ValidationError::custom only takes a message.schemaLocation in evaluation output now excludes $ref/$dynamicRef/$recursiveRef per JSON Schema spec.evaluate(): 4.5-30x faster on complex schemas, 12-89% faster overall.oneOf/anyOf: ~4000x faster via memoization. #930ValidationError.evaluation_path attribute for the dynamic path including $ref traversals.schemaLocation in evaluation output now excludes $ref/$dynamicRef/$recursiveRef per JSON Schema spec.evaluate(): 4.5-30x faster on complex schemas, 12-89% faster overall.oneOf/anyOf: ~4000x faster via memoization. #930multipleOf validation for integer values between 2^53 and i64::MAX with arbitrary-precision feature.
multipleOf validation for integer values between 2^53 and i64::MAX with arbitrary-precision feature.EmailOptions for configuring email format validation. #903
EmailOptions for configuring email format validation.multipleOf validation for large integers beyond i64::MAX.mask parameter in evaluate docstring.with_meta_schemas parameter from type stubs (was removed from the API long ago).Your coding agent can read these notes before it upgrades. Set up the MCP server →