Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/source/perf-tips.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ defining a `msgspec.Struct` type (or types) for your schema and preferring that
over other types like `dict`/`dataclasses`/...


Avoid Encoding Default Values
-----------------------------

By default, ``msgspec`` encodes all fields in a Struct type, including optional
fields (those configured with a default value). If the default values are known
on the decoding end (making serializing them redundant), it may be beneficial
to omit default values from the encoded message. This can be done by
configuring ``omit_defaults=True`` as part of the Struct definition Omitting
defaults reduces the size of the encoded message, and often also improves
encoding and decoding performance (since there's less work to do).

For more information, see :ref:`omit_defaults`.


Avoid Decoding Unused Fields
----------------------------

Expand Down
69 changes: 69 additions & 0 deletions docs/source/structs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,75 @@ for all struct types you wish to tag.
Get(key='my key')


.. _omit_defaults:

Omitting Default Values
-----------------------

By default, ``msgspec`` encodes all fields in a Struct type, including optional
fields (those configured with a default value).

.. code-block:: python

>>> import msgspec

>>> class User(msgspec.Struct):
... name : str
... email : Optional[str] = None
... groups : Set[str] = set()

>>> alice = User("alice")

>>> alice # email & groups are using the default values
User(name='alice', email=None, groups=set())

>>> msgspec.json.encode(alice) # default values are present in encoded message
b'{"name":"alice","email":null,"groups":[]}'

If the default values are known on the decoding end (making serializing them
redundant), it may be beneficial and desired to omit default values from the
encoded message. This can be done by configuring ``omit_defaults=True`` as part
of the Struct definition:

.. code-block:: python

>>> import msgspec

>>> class User(msgspec.Struct, omit_defaults=True):
... name : str
... email : Optional[str] = None
... groups : Set[str] = set()

>>> alice = User("alice")

>>> msgspec.json.encode(alice) # default values are omitted
b'{"name":"alice"}'

>>> bob = User("bob", email="bob@company.com")

>>> msgspec.json.encode(bob)
b'{"name":"bob","email":"bob@company.com"}'

Omitting defaults reduces the size of the encoded message, and often also
improves encoding and decoding performance (since there's less work to do).

Note that detection of default values is optimized for performance; in certain
situations a default value may still be encoded. For the curious, the current
detection logic is as follows:

.. code-block:: python

>>> def matches_default(value: Any, default: Any) -> bool:
... """Whether a value matches the default for a field"""
... if value is default:
... return True
... if type(value) != type(default):
... return False
... if type(value) in (list, set, dict) and (len(value) == len(default) == 0):
... return True
... return False


Encoding/Decoding as Arrays
---------------------------

Expand Down
1 change: 1 addition & 0 deletions msgspec/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Struct(metaclass=__StructMeta):
cls,
tag: Union[None, bool, str, Callable[[str], str]] = None,
tag_field: Union[None, str] = None,
omit_defaults: bool = False,
frozen: bool = False,
array_like: bool = False,
nogc: bool = False,
Expand Down
Loading