Files
pydantic/docs/usage/exporting_models.md
T
Davis Kirkendall db697cc799 Add exclude as field parameter (#2231)
* Add exclude/include as field parameters

- Add "exclude" / "include" as a field parameter so that it can be
  configured using model config (or fields) instead of purely at
  `.dict` / `.json` export time.
- Unify merging logic of advanced include/exclude fields
- Add tests for merging logic and field/config exclude/include params
- Closes #660

* Precompute include/exclude fields for class

* Increase test coverage
* Remove (now) redundant type checks in Model._iter: New
  exclusion/inclusion algorithms guarantee that no sets are passed further down.

* Add docs for advanced field level exclude/include settings

* Minimal optimization for simple exclude/include export

Running benchmarks this vs. master is at:

this: pydantic best=33.225μs/iter avg=33.940μs/iter stdev=1.120μs/iter version=1.7.3
master: pydantic best=32.901μs/iter avg=33.276μs/iter stdev=0.242μs/iter version=1.7.3

* Apply review comments on exclude/enclude field arguments

* Fix/simplify type annotations
* Allow both ``True`` and ``Ellipsis`` to be used to indicate full field
  exclusion
* Reenable hypothesis plugin (removed by mistake)
* Update advanced include/include docs to use ``True`` instead of ``...``

* Move field info exclude/include updates into FieldInfo class

This way, the model field object does not need to concern itself with
dealing with field into specific fields.
(Same was done for alias in a previous commit).

* remove double back tick in markdown.

Co-authored-by: Samuel Colvin <samcolvin@gmail.com>
2021-05-01 16:45:37 +01:00

8.2 KiB

As well as accessing model attributes directly via their names (e.g. model.foobar), models can be converted and exported in a number of ways:

model.dict(...)

This is the primary way of converting a model to a dictionary. Sub-models will be recursively converted to dictionaries.

Arguments:

  • include: fields to include in the returned dictionary; see below
  • exclude: fields to exclude from the returned dictionary; see below
  • by_alias: whether field aliases should be used as keys in the returned dictionary; default False
  • exclude_unset: whether fields which were not explicitly set when creating the model should be excluded from the returned dictionary; default False. Prior to v1.0, exclude_unset was known as skip_defaults; use of skip_defaults is now deprecated
  • exclude_defaults: whether fields which are equal to their default values (whether set or otherwise) should be excluded from the returned dictionary; default False
  • exclude_none: whether fields which are equal to None should be excluded from the returned dictionary; default False

Example:

{!.tmp_examples/exporting_models_dict.py!}

(This script is complete, it should run "as is")

dict(model) and iteration

pydantic models can also be converted to dictionaries using dict(model), and you can also iterate over a model's field using for field_name, value in model:. With this approach the raw field values are returned, so sub-models will not be converted to dictionaries.

Example:

{!.tmp_examples/exporting_models_iterate.py!}

(This script is complete, it should run "as is")

model.copy(...)

copy() allows models to be duplicated, which is particularly useful for immutable models.

Arguments:

  • include: fields to include in the returned dictionary; see below
  • exclude: fields to exclude from the returned dictionary; see below
  • update: a dictionary of values to change when creating the copied model
  • deep: whether to make a deep copy of the new model; default False

Example:

{!.tmp_examples/exporting_models_copy.py!}

(This script is complete, it should run "as is")

model.json(...)

The .json() method will serialise a model to JSON. Typically, .json() in turn calls .dict() and serialises its result. (For models with a custom root type, after calling .dict(), only the value for the __root__ key is serialised)

Arguments:

  • include: fields to include in the returned dictionary; see below
  • exclude: fields to exclude from the returned dictionary; see below
  • by_alias: whether field aliases should be used as keys in the returned dictionary; default False
  • exclude_unset: whether fields which were not set when creating the model and have their default values should be excluded from the returned dictionary; default False. Prior to v1.0, exclude_unset was known as skip_defaults; use of skip_defaults is now deprecated
  • exclude_defaults: whether fields which are equal to their default values (whether set or otherwise) should be excluded from the returned dictionary; default False
  • exclude_none: whether fields which are equal to None should be excluded from the returned dictionary; default False
  • encoder: a custom encoder function passed to the default argument of json.dumps(); defaults to a custom encoder designed to take care of all common types
  • **dumps_kwargs: any other keyword arguments are passed to json.dumps(), e.g. indent.

pydantic can serialise many commonly used types to JSON (e.g. datetime, date or UUID) which would normally fail with a simple json.dumps(foobar).

{!.tmp_examples/exporting_models_json.py!}

(This script is complete, it should run "as is")

json_encoders

Serialisation can be customised on a model using the json_encoders config property; the keys should be types, and the values should be functions which serialise that type (see the example below):

{!.tmp_examples/exporting_models_json_encoders.py!}

(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.

{!.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:

{!.tmp_examples/exporting_models_json_subclass.py!}

(This script is complete, it should run "as is")

Custom JSON (de)serialisation

To improve the performance of encoding and decoding JSON, alternative JSON implementations (e.g. ujson) can be used via the json_loads and json_dumps properties of Config.

{!.tmp_examples/exporting_models_ujson.py!}

(This script is complete, it should run "as is")

ujson generally cannot be used to dump JSON since it doesn't support encoding of objects like datetimes and does not accept a default fallback function argument. To do this, you may use another library like orjson.

{!.tmp_examples/exporting_models_orjson.py!}

(This script is complete, it should run "as is")

Note that orjson takes care of datetime encoding natively, making it faster than json.dumps but meaning you cannot always customise the encoding using Config.json_encoders.

pickle.dumps(model)

Using the same plumbing as copy(), pydantic models support efficient pickling and unpickling.

{!.tmp_examples/exporting_models_pickle.py!}

(This script is complete, it should run "as is")

Advanced include and exclude

The dict, json, and copy methods support include and exclude arguments which can either be sets or dictionaries. This allows nested selection of which fields to export:

{!.tmp_examples/exporting_models_exclude1.py!}

The True indicates that we want to exclude or include an entire key, just as if we included it in a set. Of course, the same can be done at any depth level.

Special care must be taken when including or excluding fields from a list or tuple of submodels or dictionaries. In this scenario, dict and related methods expect integer keys for element-wise inclusion or exclusion. To exclude a field from every member of a list or tuple, the dictionary key '__all__' can be used as follows:

{!.tmp_examples/exporting_models_exclude2.py!}

The same holds for the json and copy methods.

Model and field level include and exclude

In addition to the explicit arguments exclude and include passed to dict, json and copy methods, we can also pass the include/exclude arguments directly to the Field constructor or the equivalent field entry in the models Config class:

{!.tmp_examples/exporting_models_exclude3.py!}

In the case where multiple strategies are used, exclude/include fields are merged according to the following rules:

  • First, model config level settings (via "fields" entry) are merged per field with the field constructor settings (i.e. Field(..., exclude=True)), with the field constructor taking priority.
  • The resulting settings are merged per class with the explicit settings on dict, json, copy calls with the explicit settings taking priority.

Note that while merging settings, exclude entries are merged by computing the "union" of keys, while include entries are merged by computing the "intersection" of keys.

The resulting merged exclude settings:

{!.tmp_examples/exporting_models_exclude4.py!}

are the same as using merged include settings as follows:

{!.tmp_examples/exporting_models_exclude5.py!}