Open
Conversation
Add comprehensive OpenAPI 3.1 / JSON Schema 2020-12 support: - Type arrays with null support (e.g., ["string", "null"]) - JSON Schema 2020-12 keywords: const, examples, prefixItems, contains, minContains, maxContains, patternProperties, dependentSchemas, propertyNames, unevaluatedItems, unevaluatedProperties - Conditional keywords: if/then/else, dependentRequired - ExclusiveBound union type for 3.0 (boolean) and 3.1 (numeric) exclusive bounds - Webhooks support with $ref resolution - Version detection helpers: IsOpenAPI3_0(), IsOpenAPI3_1() - Info.Summary and License.Identifier fields - JSON Schema 2020-12 validator via EnableJSONSchema2020() - Document-level validation option: EnableJSONSchema2020Validation() - Allow $ref alongside other keywords in 3.1 schemas - Handle "null" type in schema validation - Auto-detect 3.1 in cmd/validate Co-Authored-By: Chance Kirsch <> Co-Authored-By: RobbertDM <> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…, etc.) The loader's resolveSchemaRef only resolved $ref in pre-3.1 fields (items, properties, additionalProperties, not, allOf, anyOf, oneOf). References inside the new OpenAPI 3.1 / JSON Schema 2020-12 fields were silently left unresolved, causing nil Value pointers. This adds ref resolution for: prefixItems, contains, patternProperties, dependentSchemas, propertyNames, unevaluatedItems, unevaluatedProperties. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The OpenAPI-to-JSON-Schema transformation only recursed into pre-3.1 fields (properties, additionalProperties, items, not, oneOf, anyOf, allOf). Nested schemas inside 3.1 fields with OpenAPI 3.0-isms like nullable:true were not converted, causing incorrect validation. This adds recursion into: prefixItems, contains, patternProperties, dependentSchemas, propertyNames, unevaluatedItems, unevaluatedProperties. Also consolidates the properties/patternProperties/dependentSchemas map iteration into a single loop. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Schema.Validate() (used by doc.Validate()) recursively validates sub-schemas in Items, Properties, AdditionalProperties, etc. but did not recurse into the new OpenAPI 3.1 / JSON Schema 2020-12 fields. Invalid sub-schemas nested inside these fields went undetected. This adds validation for: prefixItems, contains, patternProperties, dependentSchemas, propertyNames, unevaluatedItems, unevaluatedProperties. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make paths optional in 3.1 (required only in 3.0) - Add mutualTLS security scheme type validation - Validate license url/identifier mutual exclusivity - Enable JSON Schema 2020-12 validation in openapi3filter for 3.1 docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add $id, $anchor, $dynamicRef, $dynamicAnchor identity keywords - Add contentMediaType, contentEncoding, contentSchema vocabulary - Add discriminator support for anyOf (was only oneOf) - Validate jsonSchemaDialect as valid URI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- IsEmpty(): add missing checks for PrefixItems, Contains, MinContains, MaxContains, PatternProperties, DependentSchemas, PropertyNames, UnevaluatedItems, UnevaluatedProperties, Examples - JSONLookup(): add all 23 missing JSON Schema 2020-12 field cases - validate(): relax items requirement for arrays when in 3.1 mode or when prefixItems is present - transformOpenAPIToJSONSchema: clean up exclusiveMinimum/Maximum false, handle nullable:true without type field - MarshalYAML: only emit paths when non-nil (valid in 3.1) - visitConstOperation: use reflect.DeepEqual for json.Number comparison - Webhooks validation: use componentNames() for deterministic ordering Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rephrase text to not contain literal json struct tag syntax that triggers the json/yaml tag consistency check. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Open issues are tracked in the PR getkin#1125 description instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add $comment keyword to Schema struct (MarshalYAML, UnmarshalJSON, IsEmpty, JSONLookup) - Fix PrefixItems type from []*SchemaRef to SchemaRefs for consistency with OneOf/AnyOf/AllOf and JSON Pointer support - Fix exclusiveBoundToBool data loss: preserve numeric bound value when converting OAS 3.1 exclusive bounds to OAS 2.0 - Auto-enable JSON Schema 2020-12 validation for OpenAPI 3.1 documents in doc.Validate() so library users don't need explicit opt-in - Add ref resolution tests for if/then/else and contentSchema - Add transform test for contentSchema with nullable nested schema - Add validate test for contentSchema with invalid sub-schema - Document breaking API changes in README (ExclusiveBound, PrefixItems) - Regenerate docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add $schema keyword to Schema struct for per-schema dialect declaration - Add $defs keyword (Schemas map) for local reusable schema definitions, with full support: struct, marshal, unmarshal, IsEmpty, JSONLookup, validate (recurse), loader (resolve refs), transform (recurse) - Fix jsonSchemaDialect URI validation to require a scheme - Refactor discriminator resolution into shared helper to eliminate code duplication between oneOf and anyOf paths - Regenerate docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OpenAPI 3.1 adds Const (any) and Examples ([]any) fields to Schema. Like Enum/Default/Example, these can contain arbitrary JSON/YAML values that pick up __origin__ metadata from the YAML loader. Strip it on unmarshal to prevent false diffs and unexpected metadata in parsed values. Adds TestOrigin_ConstAndExamplesStripped regression test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The origin-tracking YAML loader injects __origin__ as a key inside any map-valued field to record source location. However, typed Go maps (map[string]*Encoding, map[string]*ServerVariable, map[string]*PathItem) treat __origin__ as a real entry, causing false positive diffs when the same spec is loaded from two different file paths. Fix by deleting originKey from these three maps after JSON unmarshaling, mirroring the existing pattern used for Extensions and the unmarshalStringMapP helper already used by Content, Schemas, Headers, etc. Affected: - MediaType.Encoding (map[string]*Encoding) - Server.Variables (map[string]*ServerVariable) - T.Webhooks (map[string]*PathItem) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implement scoped OpenAPI 3.1 features for CGo validation library: - P0-1: Fall back to built-in validator when JSON Schema 2020-12 compilation fails (e.g. unresolved cross-schema $ref) - P0-2: Merge $ref sibling keywords (description, title, default, example, nullable, etc.) for OpenAPI 3.1 documents only - P1-3: Add patternProperties validation in visitJSONObject with proper regex matching and error handling - P1-4: Add prefixItems positional validation in visitJSONArray - P1-5: Fix const:null ambiguity via ConstIsSet field detection in UnmarshalJSON, supporting both JSON-parsed and programmatic schemas - P1-6: Treat format as annotation-only in OpenAPI 3.1 mode - P2-7: Add $anchor fragment resolution in loader - P2-8: Add $dynamicAnchor indexing in loader Also fixes: - nullable transform uses []any instead of []string for jsonschema compiler compatibility - Remove unsafe pointer-based validator cache that caused stale validator reuse across GC cycles Ref: #2
- loader: reset anchorIndex/dynamicAnchorIndex in resetVisitedPathItemRefs to prevent anchor leaks on Loader reuse
- loader: set refPath on SchemaRef when resolving anchors, consistent with other resolution paths
- schema: fix ExclusiveBound.MarshalJSON to return []byte("null") instead of nil,nil
- schema: fix nullable handling in JSON Schema validator; only add null to type when type is explicitly set
- test: replace empty if-blocks with require.False/True assertions in issue230_test.go
- test: fix misplaced test function comments in origin_test.go
- test: canonicalize HTTP header keys in components_path_items_maingo_test.go
- docs: update doc.go, schema.go, schema_validation_settings.go comments; regenerate openapi3.txt
- schema: fix const:null handling — IsEmpty() and MarshalJSON() now use ConstIsSet flag so that an explicit 'const: null' is preserved and not treated as an absent keyword - schema: return foundUnresolvedRef for unresolved prefixItems entries instead of silently continuing, matching the behavior of items/properties - schema: patternProperties now uses settings.regexCompiler when set and returns foundUnresolvedRef for unresolved schema refs, matching the validator's standard behavior
Add an internal isOpenAPI31 flag to ValidationOptions, injected automatically by T.Validate() for 3.1 documents. SecurityScheme.Validate() now returns an error when mutualTLS is used in a non-3.1 context. Addresses CodeRabbit comment #2991964095.
- CI: use require.ErrorContains instead of require.Contains(err.Error())
in TestMutualTLSVersionGating
- openapi3/openapi3.go: enforce OAS 3.1 requires at least one of paths,
webhooks, or components (spec §4.7.1)
- openapi2conv: fix effectiveMin/Max and exclusiveMinToBool/exclusiveMaxToBool
so that {minimum:5, exclusiveMinimum:3} converts correctly (>= 5, not > 5)
- openapi3/schema_const_test.go: fix 'null const' test to use ConstIsSet:true
and type:null so the const check is actually exercised
- openapi3/schema_jsonschema_validator_test.go: rename fallback test to
CompilationFallback, document why fallback exists; fix
TestBuiltInValidatorStillWorks first sub-test to omit EnableJSONSchema2020
- openapi3/schema_jsonschema_validator.go: add comment explaining why the
fallback from newJSONSchemaValidator to built-in is intentional (internal
document $refs cannot be resolved in standalone compilation)
- openapi3/schema.go: cache patternProperties regex via compiledPatterns
sync.Map, mirroring the existing pattern field caching
…m JSON Schema validator When formatValidationError creates SchemaError instances, it now attaches the original value, schema, and customizeMessageError function from settings. This ensures SchemaError.Error() prints correct schema/value details instead of null, and that user-supplied SetSchemaErrorMessageCustomizer callbacks are invoked for errors produced by the JSON Schema 2020-12 validator path.
added 4 commits
April 1, 2026 10:54
Only index schema anchors when visiting canonical inline definitions (component.Ref == ). This prevents sibling-merged copies from overwriting anchorIndex entries with per-reference overrides, and pre-indexes component schema anchors before schema ref traversal to reduce forward-reference order dependence within components.
When ConstIsSet is true and Const is nil, the legacy visitJSONNull path now permits null values, matching visitConstOperation behavior and JSON Schema 2020-12 validation. Added regression tests for const:null without type in the built-in validator path.
…hemas Only permit nil via the visitJSONNull const:null shortcut when schema does not explicitly constrain nullability/type (Type == nil and Nullable == false). Add regression test that type:string + const:null still rejects nil.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Comprehensive OpenAPI 3.1 / JSON Schema 2020-12 support, building on the base implementation in getkin/kin-openapi#1125.
This PR adds the remaining implementation on top of that base: built-in validator enhancements,
components/pathItemssupport, and anchor resolution.What this PR does
1.
components/pathItems— full implementation (OAS 3.1)OAS 3.1 added
components/pathItemsfor reusable path items referenced via$reffrompaths.PathItems map[string]*PathItemtype withJSONLookupfor JSON Pointer supportComponents.PathItems PathItemsfield with full marshal/unmarshal/validateUnmarshalJSONdeletes"pathItems"from Extensions (no longer treated as unknown extension)Components.Validate()iterates and validates each pathItem entryLoader.ResolveRefsIn()now iteratescomponents.PathItemsand resolves$refwithin each PathItemMarshalYAMLemitspathItemswhen non-emptyTests added:
openapi3/loader_test.go:TestLoadComponentsPathItems— verifies loader resolves $ref in components/pathItemsrouters/gorillamux/router_test.go:TestRouterComponentsPathItems— verifies router finds routes through components/pathItems $refopenapi3filter/validate_request_test.go:TestValidateRequestComponentsPathItems— verifies request validation through components/pathItems $refopenapi3filter/components_path_items_test.go:TestComponentsPathItemsDocValidate,TestComponentsPathItemsRefResolved,TestComponentsPathItemsRouterAndValidationopenapi3filter/components_path_items_maingo_test.go:TestComponentsPathItemsValidateRequestSimulateMainGo2. Built-in validator enhancements (OAS 3.1 / JSON Schema 2020-12)
Features implemented directly in the built-in validator (
schema.go) without requiringEnableJSONSchema2020():prefixItems— positional tuple validationvisitJSONArrayvalidates each array element against its correspondingprefixItemsschema by positionitemsschema now applies only to elements beyond the prefixItems tuple length (correct 3.1 semantics; in 3.0,itemsapplied to all elements)patternProperties— pattern-based property validationvisitJSONObjectcompiles each pattern, matches against property names, and validates matched valuesmatchedPatternset for correctadditionalPropertiesinteractionconst: null— null value constraint (ConstIsSet flag)ConstIsSet boolfield (not serialized) that is set byUnmarshalJSONwhen"const"key is presentvisitConstOperationskips only when!ConstIsSet && Const == nil, allowingconst: nullto correctly reject non-null valuesConst == nil, ConstIsSet == false) and "must be null" (Const == nil, ConstIsSet == true)Silent fallback fix
visitJSONWithJSONSchemapreviously silently passed validation if JSON Schema compilation failed3. Loader enhancements
$anchorfragment resolutionanchorIndex map[string]*SchemaduringresolveSchemaRefresolveComponentresolves bare fragment$refs (e.g.,"#AnchorName") by looking up the anchor index$anchorto be referenced directly by anchor name$dynamicAnchorindexingdynamicAnchorIndex map[string]*SchemaalongsideanchorIndex$dynamicRefresolution (not yet dereferenced)Sibling
$refmerge (3.1 only)$ref(e.g.,description,title,default,nullable,example) are valid and must be appliedmergeSiblingFields()in loader; applied whendoc.IsOpenAPI3_1()and sibling fields are presentdescription,title,default,readOnly,writeOnly,deprecated,nullable,example,externalDocs4. Format as annotation-only (3.1)
formatis an annotation (not a validator)visitJSONNumberandvisitJSONStringnow skip format enforcement whenuseJSONSchema2020is activeOAS 3.1 Validation Feature Coverage
prefixItems(tuple)patternPropertiesconst: null$anchorresolution$dynamicAnchorindexing$refmergetypearrays withnullexclusiveMin/Maxnumericif/then/elsedependentRequiredcontains/minContains/maxContainsunevaluatedItemsunevaluatedPropertiesdependentSchemaspropertyNamescomponents/pathItems$dynamicRefKnown limitations (follow-up work)
$dynamicRefnot dereferenced —$dynamicAnchoris indexed but$dynamicRefis not resolved during loading. Schemas using$dynamicReffor recursive polymorphism will not work correctly.if/then/else,contains,unevaluated*,dependentSchemas,propertyNames— these requireEnableJSONSchema2020(). By design for now.patternProperties+additionalProperties: falseedge case —additionalProperties: falsemay incorrectly reject properties that match a pattern property when the built-in validator is used.contentMediaType/contentEncodingnot validated — annotation-only per JSON Schema 2020-12 spec; no runtime validation.Backward compatibility
ConstIsSetis a non-serialized field; existing schemas unaffectedPathItemstype is additive; existing code usingComponentscontinues to work