mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 23:00:18 +00:00
Add merged json_encoders inheritance (#2064)
* Implement merged json_encoders inheritance * json_encoders inheritance documentation
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Add merged `json_encoders` inheritance
|
||||
@@ -0,0 +1,24 @@
|
||||
from datetime import datetime, timedelta
|
||||
from pydantic import BaseModel
|
||||
from pydantic.json import timedelta_isoformat
|
||||
|
||||
|
||||
class BaseClassWithEncoders(BaseModel):
|
||||
dt: datetime
|
||||
diff: timedelta
|
||||
|
||||
class Config:
|
||||
json_encoders = {
|
||||
datetime: lambda v: v.timestamp()
|
||||
}
|
||||
|
||||
|
||||
class ChildClassWithEncoders(BaseClassWithEncoders):
|
||||
class Config:
|
||||
json_encoders = {
|
||||
timedelta: timedelta_isoformat
|
||||
}
|
||||
|
||||
|
||||
m = ChildClassWithEncoders(dt=datetime(2032, 6, 1), diff=timedelta(hours=100))
|
||||
print(m.json())
|
||||
@@ -99,11 +99,19 @@ _(This script is complete, it should run "as is")_
|
||||
By default, `timedelta` is encoded as a simple float of total seconds. The `timedelta_isoformat` is provided
|
||||
as an optional alternative which implements ISO 8601 time diff encoding.
|
||||
|
||||
The `json_encoders` are also merged during the models inheritance with the child
|
||||
encoders taking precedence over the parent one.
|
||||
|
||||
```py
|
||||
{!.tmp_examples/exporting_models_json_encoders_merge.py!}
|
||||
```
|
||||
_(This script is complete, it should run "as is")_
|
||||
|
||||
### Serialising subclasses
|
||||
|
||||
!!! note
|
||||
New in version **v1.5**.
|
||||
|
||||
|
||||
Subclasses of common types were not automatically serialised to JSON before **v1.5**.
|
||||
|
||||
Subclasses of common types are automatically encoded like their super-classes:
|
||||
|
||||
+7
-1
@@ -169,13 +169,19 @@ class BaseConfig:
|
||||
|
||||
|
||||
def inherit_config(self_config: 'ConfigType', parent_config: 'ConfigType') -> 'ConfigType':
|
||||
namespace = {}
|
||||
if not self_config:
|
||||
base_classes = (parent_config,)
|
||||
elif self_config == parent_config:
|
||||
base_classes = (self_config,)
|
||||
else:
|
||||
base_classes = self_config, parent_config # type: ignore
|
||||
return type('Config', base_classes, {})
|
||||
namespace['json_encoders'] = {
|
||||
**getattr(parent_config, 'json_encoders', {}),
|
||||
**getattr(self_config, 'json_encoders', {}),
|
||||
}
|
||||
|
||||
return type('Config', base_classes, namespace)
|
||||
|
||||
|
||||
EXTRA_LINK = 'https://pydantic-docs.helpmanual.io/usage/model_config/'
|
||||
|
||||
@@ -170,6 +170,35 @@ def test_custom_iso_timedelta():
|
||||
assert m.json() == '{"x": "P0DT0H2M3.000000S"}'
|
||||
|
||||
|
||||
def test_json_encoder_simple_inheritance():
|
||||
class Parent(BaseModel):
|
||||
dt: datetime.datetime = datetime.datetime.now()
|
||||
timedt: datetime.timedelta = datetime.timedelta(hours=100)
|
||||
|
||||
class Config:
|
||||
json_encoders = {datetime.datetime: lambda _: 'parent_encoder'}
|
||||
|
||||
class Child(Parent):
|
||||
class Config:
|
||||
json_encoders = {datetime.timedelta: lambda _: 'child_encoder'}
|
||||
|
||||
assert Child().json() == '{"dt": "parent_encoder", "timedt": "child_encoder"}'
|
||||
|
||||
|
||||
def test_json_encoder_inheritance_override():
|
||||
class Parent(BaseModel):
|
||||
dt: datetime.datetime = datetime.datetime.now()
|
||||
|
||||
class Config:
|
||||
json_encoders = {datetime.datetime: lambda _: 'parent_encoder'}
|
||||
|
||||
class Child(Parent):
|
||||
class Config:
|
||||
json_encoders = {datetime.datetime: lambda _: 'child_encoder'}
|
||||
|
||||
assert Child().json() == '{"dt": "child_encoder"}'
|
||||
|
||||
|
||||
def test_custom_encoder_arg():
|
||||
class Model(BaseModel):
|
||||
x: datetime.timedelta
|
||||
|
||||
Reference in New Issue
Block a user