Skip to content

Commit dd6b514

Browse files
committed
Support official OAS 3.2 dialect and set it as default
1 parent 0fb8ad8 commit dd6b514

File tree

12 files changed

+284
-31
lines changed

12 files changed

+284
-31
lines changed

README.rst

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Openapi-schema-validator is a Python library that validates schema against:
2222

2323
* `OpenAPI Schema Specification v3.0 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject>`__ which is an extended subset of the `JSON Schema Specification Wright Draft 00 <http://json-schema.org/>`__.
2424
* `OpenAPI Schema Specification v3.1 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#schemaObject>`__ which is an extended superset of the `JSON Schema Specification Draft 2020-12 <http://json-schema.org/>`__.
25-
* `OpenAPI Schema Specification v3.2 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.2.0.md#schemaObject>`__ which uses the same JSON Schema dialect as v3.1.
25+
* `OpenAPI Schema Specification v3.2 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.2.0.md#schemaObject>`__ using the published OAS 3.2 JSON Schema dialect resources.
2626

2727

2828
Documentation
@@ -100,25 +100,32 @@ To validate an OpenAPI v3.1 schema:
100100
101101
By default, the latest OpenAPI schema syntax is expected.
102102

103-
The OpenAPI 3.1 base dialect URI is registered for
103+
The OpenAPI 3.1 and 3.2 base dialect URIs are registered for
104104
``jsonschema.validators.validator_for`` resolution.
105-
Schemas declaring
106-
``"$schema": "https://spec.openapis.org/oas/3.1/dialect/base"``
107-
resolve directly to ``OAS31Validator`` without unresolved-metaschema
108-
fallback warnings.
105+
Schemas declaring ``"$schema"`` as either
106+
``"https://spec.openapis.org/oas/3.1/dialect/base"`` or
107+
``"https://spec.openapis.org/oas/3.2/dialect/2025-09-17"`` resolve
108+
directly to ``OAS31Validator`` and ``OAS32Validator`` without
109+
unresolved-metaschema fallback warnings.
109110

110111
.. code-block:: python
111112
112113
from jsonschema.validators import validator_for
113114
114115
from openapi_schema_validator import OAS31Validator
116+
from openapi_schema_validator import OAS32Validator
115117
116118
schema = {
117119
"$schema": "https://spec.openapis.org/oas/3.1/dialect/base",
118120
"type": "object",
119121
}
122+
schema32 = {
123+
"$schema": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17",
124+
"type": "object",
125+
}
120126
121127
assert validator_for(schema) is OAS31Validator
128+
assert validator_for(schema32) is OAS32Validator
122129
123130
124131
Strict vs Pragmatic Validators

docs/format.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ You can check format for predefined OAS primitive types
1313
...
1414
ValidationError: '-12' is not a 'date'
1515
16-
For OpenAPI 3.2, use ``oas32_format_checker`` (behaves identically to ``oas31_format_checker``, since 3.2 uses the same JSON Schema dialect).
16+
For OpenAPI 3.2, use ``oas32_format_checker``.

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Openapi-schema-validator is a Python library that validates schema against:
1414

1515
* `OpenAPI Schema Specification v3.0 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject>`__ which is an extended subset of the `JSON Schema Specification Wright Draft 00 <http://json-schema.org/>`__.
1616
* `OpenAPI Schema Specification v3.1 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#schemaObject>`__ which is an extended superset of the `JSON Schema Specification Draft 2020-12 <http://json-schema.org/>`__.
17-
* `OpenAPI Schema Specification v3.2 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.2.0.md#schemaObject>`__ which uses the same JSON Schema dialect as v3.1.
17+
* `OpenAPI Schema Specification v3.2 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.2.0.md#schemaObject>`__ using the published OAS 3.2 JSON Schema dialect resources.
1818

1919
Installation
2020
------------

docs/validation.rst

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,26 +67,33 @@ if you want to disambiguate the expected schema version, import and use ``OAS31V
6767
6868
validate({"name": "John", "age": 23}, schema, cls=OAS31Validator)
6969
70-
The OpenAPI 3.1 base dialect URI is registered for
70+
The OpenAPI 3.1 and 3.2 base dialect URIs are registered for
7171
``jsonschema.validators.validator_for`` resolution.
7272
If your schema declares
73-
``"$schema": "https://spec.openapis.org/oas/3.1/dialect/base"``,
74-
``validator_for`` resolves directly to ``OAS31Validator`` without
75-
unresolved-metaschema fallback warnings.
73+
``"$schema": "https://spec.openapis.org/oas/3.1/dialect/base"`` or
74+
``"$schema": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17"``,
75+
``validator_for`` resolves directly to ``OAS31Validator`` or
76+
``OAS32Validator`` without unresolved-metaschema fallback warnings.
7677

7778
.. code-block:: python
7879
7980
from jsonschema.validators import validator_for
8081
8182
from openapi_schema_validator import OAS31Validator
83+
from openapi_schema_validator import OAS32Validator
8284
8385
schema = {
8486
"$schema": "https://spec.openapis.org/oas/3.1/dialect/base",
8587
"type": "object",
8688
}
89+
schema32 = {
90+
"$schema": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17",
91+
"type": "object",
92+
}
8793
assert validator_for(schema) is OAS31Validator
94+
assert validator_for(schema32) is OAS32Validator
8895
89-
For OpenAPI 3.2, use ``OAS32Validator`` (behaves identically to ``OAS31Validator``, since 3.2 uses the same JSON Schema dialect).
96+
For OpenAPI 3.2, use ``OAS32Validator``.
9097

9198
In order to validate OpenAPI 3.0 schema, import and use ``OAS30Validator`` instead of ``OAS31Validator``.
9299

openapi_schema_validator/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_ID
2+
from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_ID
13
from openapi_schema_validator._format import oas30_format_checker
24
from openapi_schema_validator._format import oas30_strict_format_checker
35
from openapi_schema_validator._format import oas31_format_checker
@@ -28,4 +30,6 @@
2830
"oas31_format_checker",
2931
"OAS32Validator",
3032
"oas32_format_checker",
33+
"OAS31_BASE_DIALECT_ID",
34+
"OAS32_BASE_DIALECT_ID",
3135
]

openapi_schema_validator/_dialects.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,19 @@
99
__all__ = [
1010
"OAS31_BASE_DIALECT_ID",
1111
"OAS31_BASE_DIALECT_METASCHEMA",
12+
"OAS32_BASE_DIALECT_ID",
13+
"OAS32_BASE_DIALECT_METASCHEMA",
1214
"register_openapi_dialect",
1315
]
1416

1517
OAS31_BASE_DIALECT_ID = "https://spec.openapis.org/oas/3.1/dialect/base"
1618
OAS31_BASE_DIALECT_METASCHEMA = OPENAPI_SPECIFICATIONS.contents(
1719
OAS31_BASE_DIALECT_ID,
1820
)
21+
OAS32_BASE_DIALECT_ID = "https://spec.openapis.org/oas/3.2/dialect/2025-09-17"
22+
OAS32_BASE_DIALECT_METASCHEMA = OPENAPI_SPECIFICATIONS.contents(
23+
OAS32_BASE_DIALECT_ID,
24+
)
1925

2026
_REGISTERED_VALIDATORS: dict[tuple[str, str], Any] = {}
2127

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"$id": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"title": "OpenAPI 3.2 Schema Object Dialect",
5+
"description": "A JSON Schema dialect describing schemas found in OpenAPI v3.2.x Descriptions",
6+
"$dynamicAnchor": "meta",
7+
"$vocabulary": {
8+
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
9+
"https://json-schema.org/draft/2020-12/vocab/content": true,
10+
"https://json-schema.org/draft/2020-12/vocab/core": true,
11+
"https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
12+
"https://json-schema.org/draft/2020-12/vocab/meta-data": true,
13+
"https://json-schema.org/draft/2020-12/vocab/unevaluated": true,
14+
"https://json-schema.org/draft/2020-12/vocab/validation": true,
15+
"https://spec.openapis.org/oas/3.2/vocab/base": false
16+
},
17+
"allOf": [
18+
{
19+
"$ref": "https://json-schema.org/draft/2020-12/schema"
20+
},
21+
{
22+
"$ref": "https://spec.openapis.org/oas/3.2/meta/2025-09-17"
23+
}
24+
]
25+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
{
2+
"$id": "https://spec.openapis.org/oas/3.2/meta/2025-09-17",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"title": "OAS Base Vocabulary",
5+
"description": "A JSON Schema Vocabulary used in the OpenAPI JSON Schema Dialect",
6+
"$dynamicAnchor": "meta",
7+
"$vocabulary": {
8+
"https://spec.openapis.org/oas/3.2/vocab/base": true
9+
},
10+
"type": [
11+
"object",
12+
"boolean"
13+
],
14+
"properties": {
15+
"discriminator": {
16+
"$ref": "#/$defs/discriminator"
17+
},
18+
"example": {
19+
"deprecated": true
20+
},
21+
"externalDocs": {
22+
"$ref": "#/$defs/external-docs"
23+
},
24+
"xml": {
25+
"$ref": "#/$defs/xml"
26+
}
27+
},
28+
"$defs": {
29+
"discriminator": {
30+
"$ref": "#/$defs/extensible",
31+
"properties": {
32+
"mapping": {
33+
"additionalProperties": {
34+
"type": "string"
35+
},
36+
"type": "object"
37+
},
38+
"defaultMapping": {
39+
"type": "string"
40+
},
41+
"propertyName": {
42+
"type": "string"
43+
}
44+
},
45+
"type": "object",
46+
"unevaluatedProperties": false
47+
},
48+
"extensible": {
49+
"patternProperties": {
50+
"^x-": true
51+
}
52+
},
53+
"external-docs": {
54+
"$ref": "#/$defs/extensible",
55+
"properties": {
56+
"description": {
57+
"type": "string"
58+
},
59+
"url": {
60+
"format": "uri-reference",
61+
"type": "string"
62+
}
63+
},
64+
"required": [
65+
"url"
66+
],
67+
"type": "object",
68+
"unevaluatedProperties": false
69+
},
70+
"xml": {
71+
"$ref": "#/$defs/extensible",
72+
"properties": {
73+
"nodeType": {
74+
"type": "string",
75+
"enum": [
76+
"element",
77+
"attribute",
78+
"text",
79+
"cdata",
80+
"none"
81+
]
82+
},
83+
"name": {
84+
"type": "string"
85+
},
86+
"namespace": {
87+
"format": "iri",
88+
"type": "string"
89+
},
90+
"prefix": {
91+
"type": "string"
92+
},
93+
"attribute": {
94+
"type": "boolean",
95+
"deprecated": true
96+
},
97+
"wrapped": {
98+
"type": "boolean",
99+
"deprecated": true
100+
}
101+
},
102+
"type": "object",
103+
"dependentSchemas": {
104+
"nodeType": {
105+
"properties": {
106+
"attribute": false,
107+
"wrapped": false
108+
}
109+
}
110+
},
111+
"unevaluatedProperties": false
112+
}
113+
}
114+
}

openapi_schema_validator/shortcuts.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
from jsonschema.protocols import Validator
77

88
from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_ID
9-
from openapi_schema_validator.validators import OAS31Validator
9+
from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_ID
10+
from openapi_schema_validator.validators import OAS32Validator
1011
from openapi_schema_validator.validators import check_openapi_schema
1112

1213

1314
def validate(
1415
instance: Any,
1516
schema: Mapping[str, Any],
16-
cls: type[Validator] = OAS31Validator,
17+
cls: type[Validator] = OAS32Validator,
1718
*args: Any,
1819
**kwargs: Any
1920
) -> None:
@@ -24,11 +25,11 @@ def validate(
2425

2526
meta_schema = getattr(cls, "META_SCHEMA", None)
2627
# jsonschema's default check_schema path does not accept a custom
27-
# registry, so for the OAS 3.1 dialect we use the package registry
28+
# registry, so for OAS dialects we use the package registry
2829
# explicitly to keep metaschema resolution local and deterministic.
29-
if (
30-
isinstance(meta_schema, dict)
31-
and meta_schema.get("$id") == OAS31_BASE_DIALECT_ID
30+
if isinstance(meta_schema, dict) and meta_schema.get("$id") in (
31+
OAS31_BASE_DIALECT_ID,
32+
OAS32_BASE_DIALECT_ID,
3233
):
3334
check_openapi_schema(cls, schema_dict)
3435
else:

openapi_schema_validator/validators.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from openapi_schema_validator import _types as oas_types
1616
from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_ID
1717
from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_METASCHEMA
18+
from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_ID
19+
from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_METASCHEMA
1820
from openapi_schema_validator._dialects import register_openapi_dialect
1921
from openapi_schema_validator._specifications import (
2022
REGISTRY as OPENAPI_SPECIFICATIONS,
@@ -134,6 +136,20 @@ def _build_oas31_validator() -> Any:
134136
)
135137

136138

139+
def _build_oas32_validator() -> Any:
140+
validator = extend(
141+
OAS31Validator,
142+
{},
143+
format_checker=oas_format.oas32_format_checker,
144+
)
145+
return register_openapi_dialect(
146+
validator=validator,
147+
dialect_id=OAS32_BASE_DIALECT_ID,
148+
version_name="oas32",
149+
metaschema=OAS32_BASE_DIALECT_METASCHEMA,
150+
)
151+
152+
137153
OAS30Validator = _build_oas30_validator()
138154
OAS30StrictValidator = extend(
139155
OAS30Validator,
@@ -162,13 +178,4 @@ def _build_oas31_validator() -> Any:
162178
)
163179

164180
OAS31Validator = _build_oas31_validator()
165-
166-
# OAS 3.2 uses JSON Schema Draft 2020-12 as its base dialect, same as
167-
# OAS 3.1. The OAS-specific vocabulary differs slightly (e.g. xml keyword
168-
# changes), but since xml is not_implemented in the current validators,
169-
# the behavior is equivalent.
170-
OAS32Validator = extend(
171-
OAS31Validator,
172-
{},
173-
format_checker=oas_format.oas32_format_checker,
174-
)
181+
OAS32Validator = _build_oas32_validator()

0 commit comments

Comments
 (0)