I have a json that looks like the following, exported from pandas Dataframe:
{"columns": ["x", "y", "z"], "data": [[0, 0, 0.5], [1, 1, null]]}
This, I want to send to a FastAPI and validate using pydantic.
"columns"
equals the list ["x", "y", "z"]
"data"
is a list of format [int, int, Optional[float]]
. How can I enforce that?The closest I got so far is the following:
class MyModel(BaseModel):
columns: List[Literal['x', 'y', 'z']] = ['x', 'y', 'z']
data: List[conlist(Union[int, Optional[float]], min_length=3, max_length=3)]
However, this would also allow columns = ['x', 'x', 'x'] or data = [0,0,0]
You are on the right track. You can use field_validator
to perform complex validations:
class MyModel(BaseModel):
columns: List[conlist(str, min_length=3, max_length=3)]
data: List[conlist(Optional[float], min_items=3, max_items=3)]
@field_validator("columns")
def validate_columns(cls, value):
for row in value:
if row != ["x", "y", "z"]:
raise ValueError("columns must be exactly ['x', 'y', 'z']")
return value
@field_validator("data", mode="before")
def validate_data(cls, value):
for row in value:
if not (isinstance(row[0], int) and isinstance(row[1], int)):
raise ValueError("First two values aren't int.")
if row[2] is not None and not isinstance(row[2], float):
raise ValueError("The third value should be None or float.")
return value