-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unexpected model serialization based on the field annotation and the extra
configuration
#9043
Comments
Thanks for your question. The reason for the discrepancy here compared to V1 behavior is because of changes in how subclasses are serialized. To achieve V1-like behavior in all of the above cases, you can use the from typing import Optional
from pydantic import BaseModel, ConfigDict, Field, SerializeAsAny
param_1 = "allow"
param_2 = "forbid"
class BaseConfiguration(BaseModel):
a: int = Field(default=1)
model_config = ConfigDict(extra=param_1)
class SubConfiguration(BaseConfiguration):
b: str = Field(default="2")
model_config = ConfigDict(extra=param_2)
param_3 = SerializeAsAny[BaseConfiguration]
class MyModel(BaseModel):
config: Optional[param_3] = Field(default=None)
model_config = ConfigDict(validate_assignment=True)
sub_config = SubConfiguration()
my_model = MyModel(config=sub_config)
print(my_model.model_dump()) You can read more about this setting here. Regarding the case you've linked above, the serialization warning does seem odd. Leaving this open until we figure that out... |
Here's a more simple repro of this bug: from pydantic import BaseModel, ConfigDict, Field, TypeAdapter
class Base(BaseModel):
a: int = Field(default=1)
model_config = ConfigDict(extra='allow')
class Sub(Base):
b: str = Field(default="2")
model_config = ConfigDict(extra='forbid')
sub = Sub()
print(repr(sub))
#> Sub(a=1, b='2')
print(sub.model_dump())
#> {'a': 1, 'b': '2'}
ta = TypeAdapter(Base)
result = ta.dump_python(sub)
"""
/Users/programming/pydantic_work/pydantic/pydantic/type_adapter.py:356: UserWarning: Pydantic serializer warnings:
Expected `general-fields` but got `tuple` - serialized value may not be as expected
return self.serializer.to_python(
"""
print(result)
#> ({'a': 1, 'b': '2'}, None) |
Hey @sydney-runkle, thank you for the quick response, that was really helpful. I will try to adapt our code in a way so that we can use |
We'll be releasing a new |
That's great news :) This was a feature heavily used in our codebase in v1, that would help us a lot. |
Initial Checks
Description
Hey there,
I am having an issue with model serialization in Pydantic v2.
To showcase it, let's say I have a model called
MyModel
with aconfig
field of typeBaseConfiguration
. Depending on the use case, I want to be able to assign different types of configurations to this field, or in other words, other instances of subclasses inheriting from theBaseConfiguration
class (such as theSubConfiguration
class).Creating such instances does not raise a
ValidationError
, however, while serializing these instances, I got some outputs I was not expecting. Moreover, the outcomes change again depending on theextra
parameter, set in theConfigDict
of the configuration classes.I created the following table to showcase the different behaviors:
I originally ran into this issue while migrating our codebase from pydantic v1 to v2, and we were using the use case (2) where the config field got serialized as a tuple and I got the following error as well:
In the v1 equivalent of the same example code, all cases listed above return
{'config': {'a': 1, 'b': '2'}}
which was the expected output from my side.Example Code
Python, Pydantic & OS Version
The text was updated successfully, but these errors were encountered: