The objectives are:
- Having data stored in the simplified list form or verbose dictionary/objects form.
- Having
model.Schema()
defining both formats. - Use data within application in verbose objects form.
According to this question I have tried to define the root_validator
on Hobbies:
#!/usr/bin/env python3.10
from pydantic import BaseModel, root_validator
H = {
"name": "Mark",
"hobbies": [
"Hobby1",
"Hobby2|Description of hobby 2"
]
}
class Hobby(BaseModel):
name: str
description: str | None
class Hobbies(BaseModel):
__root__: list[Hobby | str]
@root_validator(pre=True)
def convert_string_to_dict(cls, values):
"""
Converts strings to a dictionary, with an optional fields, divided by
'|' character.
"""
for idx, value in values:
if not isinstance(value, str):
continue
value = dict(zip(Hobby.__fields__, value.split("|", maxsplit=1)))
values[idx] = value
return values
class Hobbyst(BaseModel):
name: str
hobbies: Hobbies
hobbyst = Hobbyst(**H)
print(hobbyst.dict())
I axpect the script to print:
{'name': 'Mark', hobbies: [{'name': 'Hobby1', 'description': None}, {'name': 'Hobby2', 'description': 'Description of hobby 2'}]}
however I have got the following error:
Traceback (most recent call last):
File "./playground.py", line 41, in <module>
hobbyst = Hobbyst(**H)
File "pydantic/main.py", line 342, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for Hobbyst
hobbies -> __root__
too many values to unpack (expected 2) (type=value_error)
[EDIT]
I have sligtly modified the accepted answer:
@root_validator(pre=True)
def convert_string_to_dict(cls, values: dict):
"""
Converts strings to a dictionary, with an optional fields, divided by
'|' character.
"""
for idx, value in enumerate(values["__root__"]):
if not isinstance(value, str):
continue
value = dict(zip(Hobby.__fields__, value.split("|", maxsplit=1)))
values["__root__"][idx] = value
return values
I have forgotten about enumerate
and didn't know, that a dictionary instead of list will be passed to a root validator.