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

Correctly set required and nullable json schema values #43

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

martinostvik
Copy link

When using this library on models that has a json_schema_extra field populated with "nullable" False etc the resulting model will not be marked as nullable in the json schema.

pydantic-partial should mark all fields as optional in the resulting partial model.
An example is having a pydantic model with a field that has a default value.
In API responses you want the field to not be nullable (as it has a default value, it will not be null in the API response).
To acchieve this you can create a model like this:

from pydantic import BaseModel, Field

class Pet(BaseModel):
    name: str = Field(default="Charlie", json_schema_extra={"required": True})

This will make sure the field name has a default value if not provided, AND that the json schema for the API response iwll not mark it as nullable.

But for a PATCH request etc you can use pydantic-partial to create a version of this model where all fields are optional for the request body.
The issue is that this library won't override the json_schema_extra values already existing on the model.

from pydantic import BaseModel, Field
from pydantic_partial import create_partial_model

class A(BaseModel):
    name: str = Field(default="Bob", json_schema_extra={"required": True})

class B(BaseModel):
    name: str = Field(default="Bob", json_schema_extra={"nullable": False})

class C(BaseModel):
    name: str = Field(default="Bob")
    
PartialA = create_partial_model(A)
PartialB = create_partial_model(B)
PartialC = create_partial_model(C)

print(PartialA.model_json_schema())
print(PartialB.model_json_schema())
print(PartialC.model_json_schema())

Results before my changes:
Partial A:

{
   "properties":{
      "name":{
         "default":"Bob",
         "required":true,  <---- required and not nullable
         "title":"Name",
         "type":"string"
      }
   },
   "title":"A",
   "type":"object"
}

PartialB:

{
   "properties":{
      "name":{
         "default":"Bob",
         "nullable":false, <--- Not nullable
         "title":"Name",
         "type":"string"
      }
   },
   "title":"B",
   "type":"object"
}

PartialC: (Has a default value, and no "required" or "nullable" values. Means it is nullable)

{
   "properties":{
      "name":{
         "default":"Bob",
         "title":"Name",
         "type":"string"
      }
   },
   "title":"C",
   "type":"object"
}

Results after the changes in this PR:

PartialA:

{
   "properties":{
      "name":{
         "anyOf":[
            {
               "type":"string"
            },
            {
               "type":"null"
            }
         ],
         "default":"None",
         "nullable":true,   <---- nullable ✅
         "required":false,  <---- not required ✅
         "title":"Name"
      }
   },
   "title":"APartial",
   "type":"object"
}

PartialB:

{
   "properties":{
      "name":{
         "default":"Bob",
         "nullable":false, <---- nullable ✅
         "title":"Name",
         "type":"string"
      }
   },
   "title":"B",
   "type":"object"
}

PartialC: (Has a default value, and no "required" or "nullable" values. Means it is nullable)

{
   "properties":{
      "name":{
         "default":"Bob",
         "title":"Name",
         "type":"string"
      }
   },
   "title":"C",
   "type":"object"
}

@martinostvik martinostvik changed the title correctly set required and nullable json schema values Correctly set required and nullable json schema values Dec 1, 2024
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

Successfully merging this pull request may close these issues.

1 participant