Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

schemas are not referenced correctly in openapi.json #70

Open
amarquard089 opened this issue Dec 20, 2023 · 2 comments
Open

schemas are not referenced correctly in openapi.json #70

amarquard089 opened this issue Dec 20, 2023 · 2 comments

Comments

@amarquard089
Copy link

amarquard089 commented Dec 20, 2023

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.

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

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'}}
@pgjones
Copy link
Owner

pgjones commented May 15, 2024

I don't understand the issue here, is it that it defines the schema rather than referencing it?

@amarquard089
Copy link
Author

I don't understand the issue here, is it that it defines the schema rather than referencing it?

Yeah exactly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants