Repository navigation
fix(spec): report JSON Schema keywords that OpenAPI 3.0 does not define #867
Description
Context
OpenAPI 3.0 has no propertyNames, if/then/else, contains, unevaluatedProperties, dependentRequired, or array-valued items. When a schema carries one of them, 3.0 generation leaves it in the document. The document then fails openapi-spec-validator, no warning is emitted, and strict=True passes.
This is not limited to hand-written schemas. Pydantic v2 emits propertyNames for a dict field whose key type has constraints, so an ordinary model such as dict[Literal["a", "b"], int] produces an invalid 3.0 document.
The 3.0 residual audit only looks for type arrays and null anyOf branches, and conversion does not touch these keywords, so nothing in the pipeline notices them.
Current State
Measured with the fix from #863 applied (the state main will be in once it merges), openapi-spec-validator 0.9.0, Pydantic 2.14.2, Python 3.11, openapi_version="3.0.0" and strict=True:
| Input | Generation | Structured warnings | External validation |
|---|---|---|---|
dict[Literal["a", "b"], int] field |
succeeds | 0 | fails |
dict[Annotated[str, StringConstraints(max_length=3)], int] field |
succeeds | 0 | fails |
dict[Annotated[str, StringConstraints(pattern="^item-")], int] field |
succeeds | 0 | valid (patternProperties is already converted) |
raw {"if": ..., "then": ..., "else": ...} |
succeeds | 0 | fails |
raw {"type": "array", "contains": {...}} |
succeeds | 0 | fails |
raw {"type": "object", "unevaluatedProperties": false} |
succeeds | 0 | fails |
raw {"type": "object", "dependentRequired": {...}} |
succeeds | 0 | fails |
raw {"type": "array", "items": [{"type": "string"}]} |
succeeds | 0 | fails |
For dict[Literal["a", "b"], int] Pydantic emits {"additionalProperties": {"type": "integer"}, "propertyNames": {"enum": ["a", "b"]}, "type": "object"}.
Steps to Reproduce
from typing import Literal
from openapi_spec_validator import validate
from pydantic import BaseModel
from azure_functions_openapi import generate_openapi_report, openapi
from azure_functions_openapi.decorator import clear_openapi_registry
class Config(BaseModel):
flags: dict[Literal["a", "b"], int]
clear_openapi_registry()
@openapi(route="config", method="post", requests=Config, summary="Set config")
def set_config() -> None: ...
report = generate_openapi_report(openapi_version="3.0.0", strict=True)
print(report.warnings) # ()
validate(report.spec) # raises OpenAPIValidationErrorAcceptance Checklist
- Decide, per keyword, whether 3.0 generation drops the keyword and reports the loss, or leaves it in place and reports it. Record the decision here. Dropping
propertyNamesand reporting it matches how fix(spec): reject or report lossy OpenAPI 3.0 schema conversion #782 treats heterogeneous tuples. - With
openapi_version="3.0.0", the Pydantic models in the table above produce documents that passopenapi-spec-validator. - Every dropped or reported keyword produces a structured
version-downgrade-dropwarning that names the keyword and its location, and raises understrict=True. - Every keyword in the table is handled at every position conversion already visits (properties, items, additionalProperties, allOf/anyOf/oneOf, not, components and inline operation schemas).
- Regression tests validate the generated 3.0 document with
openapi-spec-validatorfor components and for inline positions. -
docs/configuration.mdandDESIGN.mdno longer say that keywords OpenAPI 3.0 does not define are not audited. -
make check-allpasses and coverage stays at or above 95%.
Out of scope
- OpenAPI 3.1 and 3.2 output.
- Down-converting overlapping keywords that lose a constraint (tracked separately).
- Non-schema OpenAPI 3.1 features such as
webhooksorjsonSchemaDialect.
Environment
azure-functions-openapi0.30.1 plus the change from fix(spec): convert non-null type arrays and audit inline schemas for OpenAPI 3.0 #863; Python 3.11; Pydantic 2.14.2;openapi-spec-validator0.9.0
References
- fix(spec): make OpenAPI 3.0 output valid for @validate_http bridge routes #858 and fix(spec): convert non-null type arrays and audit inline schemas for OpenAPI 3.0 #863: the 3.0 output fix during whose review this was found
- fix(spec): down-convert examples and patternProperties for OpenAPI 3.0 #695: earlier down-conversion of
patternPropertiesandexamples - fix(spec): reject or report lossy OpenAPI 3.0 schema conversion #782: lossy conversion reporting for OpenAPI 3.0
DESIGN.md, "Schema Version Conversion"
Activity
fix(spec): report keywords nested in a dropped keyword and expanded t…
test(spec): pin nested reporting for every dropped keyword and the pr…
fix(spec): drop and report JSON Schema keywords that OpenAPI 3.0 does…