Reputation: 1190
I have an input structure like this
d = {
"==": [
"%var%",
"10"
]
}
I'd like to decompose it to the Model like this:
class Model:
op_name: str # ==
lvalue: str # %var%
rvalue: str # 10
Is it possible with Pydantic?
The best I reach so far is
class Model(BaseModel):
class Expr(NamedTuple):
lvalue: str
rvalue: str
__root__: Dict[str, Expr]
It can be created from the dict and serialized to json
m = Model.parse_obj(d)
print(m)
print(m.json())
-------
__root__={'==': Expr(lvalue='%var%', rvalue='10')}
{"==": ["%var%", "10"]}
But there is no op_name
, so it's hard to deal with this model. Is it possible to decompose it into 3 fields with transparent serialization/deserialization to/from json?
Upvotes: 2
Views: 3396
Reputation: 4089
I think you can use a @root_validator
to decompose your input dict into the corresponding fields:
class Model(BaseModel):
op_name: str
lvalue: str
rvalue: str
@root_validator(pre=True)
def _decompose(cls, values: Dict[str, Any]) -> Dict[str, Any]:
new_values = {}
op_name = next(iter(values.keys()), None)
if op_name is not None:
new_values["op_name"] = op_name
list_values = values.get(op_name)
if isinstance(list_values, list) and len(list_values) == 2:
new_values["lvalue"] = list_values[0]
new_values["rvalue"] = list_values[1]
return new_values
It is important to use pre=True
to decompose the input before any other validation is applied.
See an example in Google Colab.
Upvotes: 2