Skip to content

Commit

Permalink
fix: support custom root type with nested models in parse_obj
Browse files Browse the repository at this point in the history
  • Loading branch information
PrettyWood committed Jan 5, 2021
1 parent 13a5c7d commit bbb9182
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 3 deletions.
6 changes: 3 additions & 3 deletions pydantic/main.py
Expand Up @@ -662,14 +662,14 @@ def __get_validators__(cls) -> 'CallableGenerator':

@classmethod
def validate(cls: Type['Model'], value: Any) -> 'Model':
if isinstance(value, dict):
if cls.__custom_root_type__:
return cls.parse_obj(value)
elif isinstance(value, dict):
return cls(**value)
elif isinstance(value, cls):
return value.copy()
elif cls.__config__.orm_mode:
return cls.from_orm(value)
elif cls.__custom_root_type__:
return cls.parse_obj(value)
else:
try:
value_as_dict = dict(value)
Expand Down
54 changes: 54 additions & 0 deletions tests/test_main.py
Expand Up @@ -1120,6 +1120,60 @@ class MyModel(BaseModel):
]


def test_parse_obj_nested_root():
class Pokemon(BaseModel):
name: str
level: int

class Pokemons(BaseModel):
__root__: List[Pokemon]

class Player(BaseModel):
rank: int
pokemons: Pokemons

class Players(BaseModel):
__root__: Dict[str, Player]

class Tournament(BaseModel):
players: Players
city: str

payload = {
'players': {
'Jane': {
'rank': 1,
'pokemons': [
{
'name': 'Pikachu',
'level': 100,
},
{
'name': 'Bulbasaur',
'level': 13,
},
],
},
'Tarzan': {
'rank': 2,
'pokemons': [
{
'name': 'Jigglypuff',
'level': 7,
},
],
},
},
'city': 'Qwerty',
}

tournament = Tournament.parse_obj(payload)
assert tournament.city == 'Qwerty'
assert len(tournament.players.__root__) == 2
assert len(tournament.players.__root__['Jane'].pokemons.__root__) == 2
assert tournament.players.__root__['Jane'].pokemons.__root__[0].name == 'Pikachu'


def test_untouched_types():
from pydantic import BaseModel

Expand Down

0 comments on commit bbb9182

Please sign in to comment.