Revert "Add nested json encoding (#3941)" (#4367)

This reverts commit b42fae081c.
This commit is contained in:
Samuel Colvin
2022-08-12 11:08:33 +01:00
committed by GitHub
parent b8a695788e
commit 5c8942bdd4
5 changed files with 0 additions and 145 deletions
-1
View File
@@ -1 +0,0 @@
add `use_nested_encoders` keyword argument to `BaseModel.json` to allow encoding nested subclasses with encoders specified in the inner classes
@@ -1,41 +0,0 @@
from datetime import datetime, timedelta
from pydantic import BaseModel
from pydantic.json import timedelta_isoformat
class CustomChildModel(BaseModel):
dt: datetime
diff: timedelta
class Config:
json_encoders = {
datetime: lambda v: v.timestamp(),
timedelta: timedelta_isoformat,
}
class ParentModel(BaseModel):
diff: timedelta
child: CustomChildModel
class Config:
json_encoders = {
timedelta: lambda v: v.total_seconds(),
CustomChildModel: lambda _: 'using parent encoder',
}
child = CustomChildModel(dt=datetime(2032, 6, 1), diff=timedelta(hours=100))
parent = ParentModel(diff=timedelta(hours=3), child=child)
# default encoder uses total_seconds() for diff
print(parent.json())
# nested encoder uses isoformat
print(parent.json(use_nested_encoders=True))
# turning off models_as_dict only uses the top-level formatter, however
print(parent.json(models_as_dict=False, use_nested_encoders=True))
print(parent.json(models_as_dict=False, use_nested_encoders=False))
-14
View File
@@ -118,20 +118,6 @@ In case of forward references, you can use a string with the class name instead
```
_(This script is complete, it should run "as is")_
### Nested serialisation of other models
By default, models that contain other models are serialised using the `json_encoders` functions of the
parent or container class.
However, you may want to nest classes in a modular fashion, including their `json_encoders`.
In this case, call `json(use_nested_encoders=True)`.
`use_nested_encoders` has no effect when `models_as_dict=False`, as the classes of the models
are expected to be defined in the top-level `json_encoders`.
```py
{!.tmp_examples/exporting_models_json_nested_encoders.py!}
```
_(This script is complete, it should run "as is")_
### Serialising subclasses
!!! note
-11
View File
@@ -427,7 +427,6 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
encode_as_json: bool = False,
) -> 'DictStrAny':
"""
Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
@@ -449,7 +448,6 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
encode_as_json=encode_as_json,
)
)
@@ -465,7 +463,6 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
exclude_none: bool = False,
encoder: Optional[Callable[[Any], Any]] = None,
models_as_dict: bool = True,
use_nested_encoders: bool = False,
**dumps_kwargs: Any,
) -> str:
"""
@@ -493,7 +490,6 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
encode_as_json=use_nested_encoders,
)
)
if self.__custom_root_type__:
@@ -714,7 +710,6 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
exclude_unset: bool,
exclude_defaults: bool,
exclude_none: bool,
encode_as_json: bool = False,
) -> Any:
if isinstance(v, BaseModel):
@@ -726,7 +721,6 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
include=include,
exclude=exclude,
exclude_none=exclude_none,
encode_as_json=encode_as_json,
)
if ROOT_KEY in v_dict:
return v_dict[ROOT_KEY]
@@ -776,9 +770,6 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
elif isinstance(v, Enum) and getattr(cls.Config, 'use_enum_values', False):
return v.value
elif encode_as_json:
return cls.__json_encoder__(v)
else:
return v
@@ -812,7 +803,6 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
encode_as_json: bool = False,
) -> 'TupleGenerator':
# Merge field set excludes with explicit exclude parameter with explicit overriding field set options.
@@ -858,7 +848,6 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
encode_as_json=encode_as_json,
)
yield dict_key, v
-78
View File
@@ -372,81 +372,3 @@ def test_recursive():
nested: Optional[BaseModel]
assert Model(value=None, nested=Model(value=None)).json(exclude_none=True) == '{"nested": {}}'
class WithCustomEncoders(BaseModel):
dt: datetime.datetime
diff: datetime.timedelta
class Config:
json_encoders = {
datetime.datetime: lambda v: v.timestamp(),
datetime.timedelta: timedelta_isoformat,
}
ides_of_march = datetime.datetime(44, 3, 15, tzinfo=datetime.timezone.utc)
child = WithCustomEncoders(
dt=datetime.datetime(2032, 6, 1, tzinfo=datetime.timezone.utc),
diff=datetime.timedelta(hours=100),
)
def test_inner_custom_encoding():
assert child.json() == r'{"dt": 1969660800.0, "diff": "P4DT4H0M0.000000S"}'
def test_encoding_in_parent_with_variable_encoders():
class ParentWithVariableEncoders(BaseModel):
dt: datetime.datetime
child: WithCustomEncoders
class Config:
json_encoders = {
datetime.datetime: lambda v: v.year,
datetime.timedelta: lambda v: v.total_seconds(),
}
parent = ParentWithVariableEncoders(child=child, dt=ides_of_march)
default = r'{"dt": 44, "child": {"dt": 2032, "diff": 360000.0}}'
assert parent.json() == default
# turning off models_as_dict defaults to top-level
assert parent.json(models_as_dict=False, use_nested_encoders=False) == default
assert parent.json(models_as_dict=False, use_nested_encoders=True) == default
custom = (
r'{"dt": 44, ' # parent.dt still uses the year to encode
# child uses child.json_encoders to encode
r'"child": {"dt": 1969660800.0, "diff": "P4DT4H0M0.000000S"}}'
)
assert parent.json(use_nested_encoders=True) == custom
def test_encoding_in_parent_with_class_encoders():
class ParentWithClassEncoders(BaseModel):
dt: datetime.datetime
child: WithCustomEncoders
class Config:
json_encoders = {
datetime.datetime: lambda v: v.timestamp(),
WithCustomEncoders: lambda v: {'dt': v.dt.year},
}
parent = ParentWithClassEncoders(child=child, dt=ides_of_march)
# when models_as_dict=True, the `WithCustomEncoders` encoder is ignored
default = r'{"dt": -60772291200.0, "child": {"dt": 1969660800.0, "diff": 360000.0}}'
assert parent.json() == default
custom_child = r'{"dt": -60772291200.0, "child": {"dt": 1969660800.0, "diff": "P4DT4H0M0.000000S"}}'
assert parent.json(use_nested_encoders=True) == custom_child
# when models_as_dict=False, the parent `WithCustomEncoders` is used
# regardless of whatever json_encoders are in WithCustomEncoders.Config
custom_parent = r'{"dt": -60772291200.0, "child": {"dt": 2032}}'
assert parent.json(models_as_dict=False, use_nested_encoders=False) == custom_parent
assert parent.json(models_as_dict=False, use_nested_encoders=True) == custom_parent