Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":
pydantic version: 1.7.3
pydantic compiled: True
install path: /home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/pydantic
python version: 3.9.1 (default, Jan 16 2021, 13:41:30) [GCC 9.3.0]
platform: Linux-5.4.0-62-generic-x86_64-with-glibc2.31
optional deps. installed: ['typing-extensions']
When I pass a List[str] with the string being 2 characters long (e.g. ["ab"]) to a field which is annotated with Union[Dict[str, str], List[Any]], I get a dictionary {"a": "b"} instead of ["ab"].
Example:
from typing import Union, List, Any, Dict
from pydantic import BaseModel
class Foo(BaseModel):
values: Union[Dict[str, str], List[Any]]
class Foo2(BaseModel):
values: Union[List[Any], Dict[str, str]]
print(Foo.parse_obj({"values": ["L1"]}))
print(Foo.parse_obj({"values": ["L11"]}))
print(Foo2.parse_obj({"values": ["L1"]}))
Results in:
values={'L': '1'} # Unexpected - why do I get a dict?
values=['L11'] # expected value, but surprising after seeing output (1)
values=['L1'] # expected value, but surprising after seeing output (1)
Hello @MartinThoma
Yes it's a very common issue on _pydantic_ as it tries to coerce the value with types inside the Union in order (so the first one will take precedence over the second one if possible).
So here it first tries to coerce ["L1"] with Dict[str, str], which works because dict(["11"]) == {'1': '1'}.
I'm working on a way to prevent this in https://github.com/samuelcolvin/pydantic/pull/2092. The whole behaviour will change in v2.
Please have a look at linked issues to this PR if you want more information
Most helpful comment
Hello @MartinThoma
Yes it's a very common issue on _pydantic_ as it tries to coerce the value with types inside the
Unionin order (so the first one will take precedence over the second one if possible).So here it first tries to coerce
["L1"]withDict[str, str], which works becausedict(["11"]) == {'1': '1'}.I'm working on a way to prevent this in https://github.com/samuelcolvin/pydantic/pull/2092. The whole behaviour will change in v2.
Please have a look at linked issues to this PR if you want more information