Add merged json_encoders inheritance (#2064)

* Implement merged json_encoders inheritance

* json_encoders inheritance documentation
This commit is contained in:
Arthur Pastel
2021-02-13 16:56:34 +01:00
committed by GitHub
parent b87e2492cc
commit 33c5a4dc34
5 changed files with 70 additions and 2 deletions
+1
View File
@@ -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())
+9 -1
View File
@@ -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
View File
@@ -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/'
+29
View File
@@ -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