class LocationRequest(BaseModel):
business_unit: Optional[str] = None
opening: Optional[int]
max_applicant: Optional[int]
diversity_male: Optional[int]
diversity_female: Optional[int]
class JobRoleRequest(BaseModel):
name: str
description: Optional[str] = None
work_mode: Literal["full time", "half day"]
class JobRoleCreateRequest(JobRoleRequest):
location: List[LocationRequest]
while adding null value for integer fields in sub-schema location: List[LocationRequest]
but for business_unit when i leave it is working
Need possible ways to add null value for sub-schema fields
Sample Request schema
{
"name": "Job role",
"description": "job role description",
"work_mode": "Remote",
"location": [
{
"business_unit": "busiess_unit of company 1",
"opening": 10,
"max_applicant": 4,
"diversity_male": 2
"diversity_female": 2,
}
]
}
If I pass the location list without optional fields like max_applicant or diversity_male, it should work. However, when I try to pass it without these fields, I'm getting an error.
You can check pydantic's docs: Required, optional, and nullable fields
If you want to define your field as a non required nullable field, you can simply set a default value:
max_applicant: Optional[int] = None
And if don't inform the field:
sample = {
"name": "Job role",
"description": "job role description",
"work_mode": "half day",
"location": [
{
"business_unit": "busiess_unit of company 1",
"opening": 10,
"diversity_male": 2,
"diversity_female": 2
}
]
}
print(JobRoleCreateRequest(**sample))
# name='Job role' description='job role description' work_mode='half day' location=[LocationRequest(business_unit='busiess_unit of company 1', opening=10, max_applicant=None, diversity_male=2, diversity_female=2)]
You'll get your default value for max_applicant
.
The same applies if you pass "max_applicant": null
in json
.
Note that this (got from your comments) is the same:
opening: Optional[int] = Field(0, ge=0, le=999)
Optional[int] = Field(0)
means that this field is optional, will have the default value of 0 if not present, but if it is passed can be both an integer ou a null.
It's exactly how you defined your fields. When you define a field as optional, but without giving a default value, you are saying to pydantic that this field is required when creating the model, but if the value of the field is None
, that's ok:
sample = {
"name": "Job role",
"description": "job role description",
"work_mode": "half day",
"location": [
{
"business_unit": "busiess_unit of company 1",
"opening": None, # still required to inform, but can be null
"max_applicant": None, # still required to inform, but can be null
"diversity_male": None, # still required to inform, but can be null
"diversity_female": None # still required to inform, but can be null
}
]
}
print(JobRoleCreateRequest(**sample))
# name='Job role' description='job role description' work_mode='half day' location=[LocationRequest(business_unit='busiess_unit of company 1', max_applicant=None, opening=None, diversity_male=None, diversity_female=None)]
If you want your field to be optional, but can't be null, you can define it as:
opening: int = Field(ge=0, le=999, default=0)
This way, you are telling pydantic that opening
field is not required to be informed, and it will have de default value of 0 if it's not present, but if it is present, it needs to be a non nullable integer.
If you want your field to be optional, to be possible to pass a null value, but to have a non nullable value if null is passed, you can use field_validator
:
opening: Optional[int] = Field(0, ge=0, le=999)
@field_validator("opening")
@classmethod
def assign_default_if_none(cls, v: Optional[int]) -> int:
return v or 0 # return your default value here
This way, if you payload has "opening": None
, opening won't be null anymore, it will be assigned the default value, or 0 in this case:
class LocationRequest(BaseModel):
business_unit: Optional[str] = None
max_applicant: Optional[int]
opening: Optional[int] = Field(0, ge=0, le=999)
diversity_male: Optional[int]
diversity_female: Optional[int]
@field_validator("opening")
@classmethod
def assign_default_if_none(cls, v: Optional[int]) -> int:
return v or 0
class JobRoleRequest(BaseModel):
name: str
description: Optional[str] = None
work_mode: Literal["full time", "half day"]
class JobRoleCreateRequest(JobRoleRequest):
location: List[LocationRequest]
sample = {
"name": "Job role",
"description": "job role description",
"work_mode": "half day",
"location": [
{
"business_unit": "busiess_unit of company 1",
"opening": None,
"max_applicant": None,
"diversity_male": None,
"diversity_female": None
}
]
}
print(JobRoleCreateRequest(**sample))
# name='Job role' description='job role description' work_mode='half day' location=[LocationRequest(business_unit='busiess_unit of company 1', max_applicant=None, opening=0, diversity_male=None, diversity_female=None)
Obs: In your example payload, you are passing "work_mode": "Remote"
while work_mode
can be only "full time"
or "half day"
.