I have some JSON with a structure similar to what is shown below. The threshold
list represents objects where the type can be "type": "upper_limit"
or "type": "range"
. Notice the "target"
value should be an integer or float depending on the type of the object.
{
"name": "blah",
"project": "blah blah",
"threshold": [
{
"id": "234asdflkj",
"group": "walkers",
"type": "upper_limit",
"target": 20,
"var": "distance"
},
{
"id": "asdf34asf2654",
"group": "runners",
"type": "range",
"target": 1.7,
"var": "speed"
}
]
}
Pydantic models to generate a JSON schema for the above data are given below:
class ThresholdType(str, Enum):
upper_limit = "upper_limit"
range = "range"
class ThresholdUpperLimit(BaseModel):
id: str
group: str
type: ThresholdType = "upper_limit"
target: int = Field(gt=2, le=20)
var: str
class ThresholdRange(BaseModel):
id: str
group: str
type: ThresholdType = "range"
target: float = Field(gt=0, lt=10)
var: str
class Campaign(BaseModel):
name: str
project: str
threshold: list[ThresholdUpperLimit | ThresholdRange]
The models validate the JSON, but the constraints for the target
value are being ignored for the type. For example, if a threshold object contains "type": "range", "target": 12,
then no errors are thrown because it is being parsed as an integer and therefore constraints defined by the ThresholdUpperLimit
are used; but the constraints defined by ThresholdRange
should be used because the type is "range"
. Any suggestions on how to properly handle this?
2
Answers
The most common and most wise approach would be to implement a custom "
model_validate
" method to build the schema based on the provided dictionary.Some checks for
KeyError
should be added but the idea is:I managed to enforce the correct model resolution by changing your use of enum subclassing to using a Literal.
However, this does not force
target
to be afloat
on theThresholdRange
class. Anint
will pass.