Skip to content

Commit 92d40f9

Browse files
bselman1pgjones
authored andcommitted
Enhance pydantic model schema generation
- For pydantic based models, enhance the open api schema generation by differntiating between "validation" and "serialization" models. - The default mode used by the pydantic TypeAdapter when generating JSON schemas is a "validation" schema. - Add an additional option to the `model_schema` called `schema_mode` that will execute the TypeAdapter schema generation in the selected mode. - When generating Open API paths for response models, change the schema_mode to "serialization" instead of "validation". This allows us to use models that have custom fields (e.g. computed fields or custom serialization logic) to be correctly converted to an Open API schema.
1 parent c9eeadd commit 92d40f9

File tree

2 files changed

+8
-4
lines changed

2 files changed

+8
-4
lines changed

src/quart_schema/conversion.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from dataclasses import fields, is_dataclass
44
from inspect import isclass
5-
from typing import Any, Dict, List, Optional, Type, TypeVar, Union
5+
from typing import Any, Dict, List, Literal, Optional, Type, TypeVar, Union
66

77
import humps
88
from quart import current_app
@@ -73,6 +73,8 @@ class MsgSpecValidationError(Exception): # type: ignore
7373

7474
T = TypeVar("T", bound=Model)
7575

76+
JsonSchemaMode = Literal['validation', 'serialization']
77+
7678

7779
def convert_response_return_value(
7880
result: ResponseReturnValue | HTTPException,
@@ -184,9 +186,9 @@ def model_load(
184186
raise exception_class(error)
185187

186188

187-
def model_schema(model_class: Type[Model], *, preference: Optional[str] = None) -> dict:
189+
def model_schema(model_class: Type[Model], *, preference: Optional[str] = None, schema_mode: JsonSchemaMode = "validation") -> dict:
188190
if _use_pydantic(model_class, preference):
189-
return TypeAdapter(model_class).json_schema(ref_template=PYDANTIC_REF_TEMPLATE)
191+
return TypeAdapter(model_class).json_schema(ref_template=PYDANTIC_REF_TEMPLATE, mode=schema_mode)
190192
elif _use_msgspec(model_class, preference):
191193
_, schema = schema_components([model_class], ref_template=MSGSPEC_REF_TEMPLATE)
192194
return list(schema.values())[0]

src/quart_schema/extension.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,9 @@ def _build_path(func: Callable, rule: Rule, app: Quart) -> Tuple[dict, dict]:
488488
for status_code in response_models.keys():
489489
model_class, headers_model_class = response_models[status_code]
490490
schema = model_schema(
491-
model_class, preference=app.config["QUART_SCHEMA_CONVERSION_PREFERENCE"]
491+
model_class,
492+
preference=app.config["QUART_SCHEMA_CONVERSION_PREFERENCE"],
493+
schema_mode="serialization",
492494
)
493495
definitions, schema = _split_convert_definitions(
494496
schema, app.config["QUART_SCHEMA_CONVERT_CASING"]

0 commit comments

Comments
 (0)