Description
Currently, the openapi.json is faulty in the sense that even thought the schemas in the components property exists, they are not referenced in the requests/responses section.
Code to reproduce
from quart import Quart
from quart_schema import QuartSchema
from typing import List
from dataclasses import dataclass
app = Quart(__name__)
QuartSchema(app)
@dataclass
class Student:
name: str
@dataclass
class Students:
students: List[Student]
# works:
# "schema": {
# "properties": {
# "students": {
# "items": {
# "$ref": "#/components/schemas/Students"
# },
# "title": "Students",
# "type": "array"
# }
# },
@app.get("/students")
@validate_response(model_class=Students, status_code=200)
async def get_students():
return Students(students=[Student("stud1")]), 200
# doesnt work
# expected behaviour here would be
# "schema": {
# "$ref": "#/components/schemas/Student"
# }
@app.get("/student")
@validate_response(model_class=Student, status_code=200)
async def get_student():
return Student("stud1"), 200
This might be due to pydantics GenerateJsonSchema (l. 458 in quart_schema/extensions.py), which only returns a $ref, if the model_class.pydantic_core_schema contains properties with lists of dataclasses / pydantic dataclasses. Otherwise, just the model with its field definitions is returned as json.
Possible Fix
I am not quite sure about this, but it might be beneficial to use
JsonSchemaMode = "validation" # either "validation" or "serialization" # see pydantic.json_schema.JsonSchemaMode
def_, schema = GenerateJsonSchema(ref_template=REF_TEMPLATE).generate_definitions(
[(model_class.__name__, JsonSchemaMode, model_class.__pydantic_core_schema__)]
)
def_ contains the definitions as references using the REF_TEMPLATE
assert def_ == {(model_class.__name__, JsonSchemaMode): {"$ref": "REF_TEMPLATE".format(model_class.__name__)}}
# i.e. it would look like this: {('Students', 'validation'): {'$ref': '#/components/schemas/Students'}}
# and like this if Student where used instead: {('Student', 'validation'): {'$ref': '#/components/schemas/Student'}}
schema is similar to GenerateJsonSchema(...).generate(...) but without $defs in case of nested classes. Instead it contains the nested classes with references to each other, e.g.
def_, schema = GenerateJsonSchema(ref_template=REF_TEMPLATE).generate_definitions(
[(Students.__name__, JsonSchemaMode, Students.__pydantic_core_schema__)]
)
schema = {
"Student": {"properties": ...}, # same as schema from GenerateJsonSchema(...),generate(...) for Student
"Students": {"properties": ...} # same as schema from GenerateJsonSchema(...),generate(...) for Students but without $defs
}
# and in case Student is used instead of Students:
schema = {'Student': {'properties': {...}, 'required': [...], 'title': 'Student', 'type': 'object'}}
Description Currently, the openapi.json is faulty in the sense that even thought the schemas in the components property exists, they are not referenced in the requests/responses section.
Code to reproduce
This might be due to pydantics GenerateJsonSchema (l. 458 in quart_schema/extensions.py), which only returns a $ref, if the model_class.pydantic_core_schema contains properties with lists of dataclasses / pydantic dataclasses. Otherwise, just the model with its field definitions is returned as json.
Environment Python: 3.11.5 Quart: 0.19.4 Quart-Schema: 0.18.0
Possible Fix I am not quite sure about this, but it might be beneficial to use
def_ contains the definitions as references using the REF_TEMPLATE
schema is similar to GenerateJsonSchema(...).generate(...) but without $defs in case of nested classes. Instead it contains the nested classes with references to each other, e.g.