Initial Checks
Description
Pydantic has a serialization concept called serialize as any, which can be enabled globally during serialization (using the serialize_as_any parameter) or per field (using the SerializeAsAny annotation). When used, Pydantic treats the type annotation of the field as if it were Any, and tries to infer the value using its actual type (see the documentation for more details).
Up until now, the serialize_as_any flag and SerializeAsAny annotation were behaving quite differently, and they were unified in 2.12 (actually, the serialize_as_any flag behavior was aligned to match the SerializeAsAny annotation).
Unfortunately this also led to regressions where cases that previously serialized in 2.11 no longer serialize in 2.12, because dropping the type information forces pydantic-core to use type inference, and not all types have built-in inference in pydantic-core:
from pydantic import BaseModel, IPvAnyAddress
class BugReproModel(BaseModel):
ip_address: IPvAnyAddress
bug = BugReproModel(ip_address="192.168.1.1")
json_data = bug.model_dump_json(serialize_as_any=True)
# PydanticSerializationError: Unable to serialize unknown type: <class 'ipaddress.IPv4Address'>
If you are using the serialize_as_any flag and encountering serialization errors in 2.12:
- Check if you can make use of the
SerializeAsAny annotation instead, and apply it only on fields if this is necessary.
- If you don't control the types you are serializing (e.g. a Pydantic model defined in a third party library), we'd like to know more about your
serialize_as_any usage. If you use it to achieve duck typing serialization of subclasses, we may introduce a new value for serialize_as_any(e.g. a literal 'subclasses', name TBD), on top of the existing True/False. Please share use cases in this issue so that we can decide on the best path to take.
- If you encountered issues with types such as
IPvAnyAddress, we are looking into improving our type inference logic to support these when serialize as any behavior is applied (see below).
In terms of type inference, we should define more precisely how pydantic-core performs it and expand its functionality to cover as many types as possible.
There are various ways that pydantic-core can currently perform type inference:
- built-in types such as lists, mappings, integers etc
- objects which have a
__pydantic_serializer__ attribute (and are not type objects) will use that serializer
I can think of at least two more ways which users would reasonably expect pydantic-core to perform type inference:
- objects which have a
__get_pydantic_core_schema__ attribute (and are not type objects) could generate a new serializer from it (this would increase coupling between pydantic and pydantic-core, needs design, challenges as always are config and caching)
- for the case of
SerializeAsAny annotation and serialize_as_any runtime flag, there is type information which we could use to generate a fallback serializer if inference fails
Initial Checks
Description
Pydantic has a serialization concept called serialize as any, which can be enabled globally during serialization (using the
serialize_as_anyparameter) or per field (using theSerializeAsAnyannotation). When used, Pydantic treats the type annotation of the field as if it wereAny, and tries to infer the value using its actual type (see the documentation for more details).Up until now, the
serialize_as_anyflag andSerializeAsAnyannotation were behaving quite differently, and they were unified in 2.12 (actually, theserialize_as_anyflag behavior was aligned to match theSerializeAsAnyannotation).Unfortunately this also led to regressions where cases that previously serialized in 2.11 no longer serialize in 2.12, because dropping the type information forces
pydantic-coreto use type inference, and not all types have built-in inference inpydantic-core:If you are using the
serialize_as_anyflag and encountering serialization errors in 2.12:SerializeAsAnyannotation instead, and apply it only on fields if this is necessary.serialize_as_anyusage. If you use it to achieve duck typing serialization of subclasses, we may introduce a new value forserialize_as_any(e.g. a literal'subclasses', name TBD), on top of the existingTrue/False. Please share use cases in this issue so that we can decide on the best path to take.IPvAnyAddress, we are looking into improving our type inference logic to support these when serialize as any behavior is applied (see below).In terms of type inference, we should define more precisely how
pydantic-coreperforms it and expand its functionality to cover as many types as possible.There are various ways that
pydantic-corecan currently perform type inference:__pydantic_serializer__attribute (and are not type objects) will use that serializerI can think of at least two more ways which users would reasonably expect
pydantic-coreto perform type inference:__get_pydantic_core_schema__attribute (and are not type objects) could generate a new serializer from it (this would increase coupling betweenpydanticandpydantic-core, needs design, challenges as always are config and caching)SerializeAsAnyannotation andserialize_as_anyruntime flag, there is type information which we could use to generate a fallback serializer if inference fails