Skip to content

V1.9 Name Collisions JSON model_as_dict #3583

@zrothberg

Description

@zrothberg

Checks

  • I added a descriptive title to this issue
  • I have searched (google, github) for similar issues and couldn't find anything
  • I have read and followed the docs and still think this is a bug

Bug

In 1.9 Code changed in this merge #2650 The "models_as_dict" option for json has collision issues when the class names are the same but in multiple files. This is because of the change to name in custom_pydantic_encoder. In the following code this will result in an error as DBUser.User does not have the field Address. If we force the encoder to be defined after the class this issue does not happen. The other option would be modification of update_forward_refs but that seems a lot worse.

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

  pydantic version: 1.9.0a2
  pydantic compiled: True
  install path: /PycharmProjects/pythonProject/venv/lib/python3.8/site-packages/pydantic
  python version: 3.8.9 (default, Oct 26 2021, 07:25:53)  [Clang 13.0.0 (clang-1300.0.29.30)]
 
 Tried it in 3.10 as well. 
##DBusers.py
from pydantic import BaseModel
from uuid import UUID

class User(BaseModel):
    name: str
    user_id: UUID
##this one throws Exception
from typing import List, Optional

from pydantic import BaseModel
from DBUser import User as DBUser
from uuid import uuid4

class Address(BaseModel):
    city: str
    country: str


class User(BaseModel):
    name: str
    address: Address
    friends: Optional[List['User']] = None
    connections: Optional[List[DBUser]]=None

    class Config:
        json_encoders = {
            Address: lambda a: f'{a.city} ({a.country})',
            "User": lambda u: f'{u.name} in {u.address.city} '
                              f'({u.address.country[:2].upper()})',
        }


User.update_forward_refs()

wolfgang = User(
    name='Wolfgang',
    address=Address(city='Berlin', country='Deutschland'),
    friends=[
        User(name='Pierre', address=Address(city='Paris', country='France')),
        User(name='John', address=Address(city='London', country='UK')),
    ],
    connections=[
        DBUser(name="joe",user_id=uuid4()),
        DBUser(name="Jeff", user_id=uuid4()),
    ]
)
wolfgang.json(indent=2,models_as_dict=False) ##Raises AttributeError: 'User' object has no attribute 'address'
##this one does not throw Exception

from typing import List, Optional
from pydantic import BaseModel
from DBUser import User as DBUser
from uuid import uuid4

class Address(BaseModel):
    city: str
    country: str


class User(BaseModel):
    name: str
    address: Address
    friends: Optional[List["User"]] = None
    connections: Optional[List[DBUser]]=None

    class Config:
        json_encoders = {
            Address: lambda a: f'{a.city} ({a.country})',
        }


User.update_forward_refs()

User.Config.json_encoders[User] =lambda u: f'{u.name} in {u.address.city} ' f'({u.address.country[:2].upper()})'


wolfgang = User(
    name='Wolfgang',
    address=Address(city='Berlin', country='Deutschland'),
    friends=[
        User(name='Pierre', address=Address(city='Paris', country='France')),
        User(name='John', address=Address(city='London', country='UK')),
    ],
    connections=[
        DBUser(name="joe",user_id=uuid4()),
        DBUser(name="Jeff", user_id=uuid4()),
    ]
)
print(wolfgang.json(indent=2,models_as_dict=False)) ##Does not explode

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug V1Bug related to Pydantic V1.X

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions