Overview ======== Requirements ~~~~~~~~~~~~ The ``dataclass-wizard`` library officially supports **Python 3.9+** There are no core requirements outside of the Python standard library. That being said, this library *does* utilize a few conditional dependencies: * `typing-extensions` - this is a lightweight and highly useful library that backports the most recently added features to the ``typing`` module. For more info, check out the :doc:`python_compatibility` section. Advantages ~~~~~~~~~~ - Minimal setup required. In most cases, all you need is a dataclass that sub-classes from ``JSONWizard``. - Speed. It is up to 25 times faster than libraries such as `dataclasses-json`_ that use ``marshmallow``, and about 60 x faster than libraries such as `jsons`_ which don't seem to handle dataclasses as well as you'd expect. - Adds the ability to use field properties (with default values) in dataclasses. - Automatic key transform to/from JSON (ex. *camel* to *snake*). :doc:`Custom key mappings ` also supported. - Automatic type conversion when loading from JSON or a ``dict`` object. For instance, strings are converted to boolean if a type annotation is ``List[bool]``. - Built-in support for standard Python collections, as well as most Generics from the ``typing`` module. Other commonly used types such as Enums, `defaultdict`_, and *date* and *time* objects such as :class:`datetime` are also natively supported. - Latest Python features such as `parameterized standard collections `__ can be used. - Ability to construct *ad-hoc* dataclass schemas using JSON input (either as a file or string) using the included `wiz-cli`_ utility. .. _here: https://pypi.org/project/typing-extensions/ .. _fromisoformat(): https://docs.python.org/3/library/datetime.html#datetime.date.fromisoformat .. _defaultdict: https://docs.python.org/3/library/collections.html#collections.defaultdict .. _jsons: https://pypi.org/project/jsons/ .. _`wiz-cli`: https://dcw.ritviknag.com/en/latest/wiz_cli.html .. _dataclasses-json: https://pypi.org/project/dataclasses-json/ Supported Types ~~~~~~~~~~~~~~~ .. tip:: See the section on `Special Cases`_ for additional information on how Dataclass Wizard handles JSON load/dump for special Python types. Dataclass Wizard supports a wide range of Python types, making it easier to work with complex data structures. This includes built-in types, collections, and more advanced type annotations. The following types are supported: - **Basic Types**: - ``str`` - ``int`` - ``float`` - ``bool`` - ``None`` (`docs `_) - **Binary Types**: - ``bytes`` (`docs `_) - ``bytearray`` (`docs `_) - **Decimal Type**: - ``Decimal`` (`docs `_) - **Pathlib**: - ``Path`` (`docs `_) - **Typed Collections**: Typed collections are supported for structured data, including: - ``TypedDict`` (`docs `_) - ``NamedTuple`` (`docs `_) - ``namedtuple`` (`docs `_) - **ABC Containers** (`docs `_): - ``Sequence`` (`docs `_) -- instantiated as ``tuple`` - ``MutableSequence`` (`docs `_) -- mapped to ``list`` - ``Collection`` (`docs `_) -- instantiated as ``list`` - **Type Annotations and Qualifiers**: - ``Required``, ``NotRequired``, ``ReadOnly`` (`docs `_) - ``Annotated`` (`docs `_) - ``Literal`` (`docs `_) - ``LiteralString`` (`docs `_) - ``Union`` (`docs `_) -- Also supports `using dataclasses`_. - ``Optional`` (`docs `_) - ``Any`` (`docs `_) - **Enum Types**: - ``Enum`` (`docs `_) - ``StrEnum`` (`docs `_) - ``IntEnum`` (`docs `_) - **Sets**: - ``set`` (`docs `_) - ``frozenset`` (`docs `_) - **Mappings**: - ``dict`` (`docs `_) - ``defaultdict`` (`docs `_) - ``OrderedDict`` (`docs `_) - **Sequences**: - ``list`` (`docs `_) - ``deque`` (`docs `_) - ``tuple`` (`docs `_) - **UUID**: - ``UUID`` (`docs `_) - **Date and Time**: - ``datetime`` (`docs `_) - ``date`` (`docs `_) - ``time`` (`docs `_) - ``timedelta`` (`docs `_) - **Nested Dataclasses**: Nested dataclasses are supported, allowing you to serialize and deserialize nested data structures. Starting with **v0.34.0**, recursive and self-referential dataclasses are supported out of the box when the ``v1`` option is enabled in the ``Meta`` setting (i.e., ``v1 = True``). This removes the need for custom settings like ``recursive_classes`` and expands type support beyond what is available in ``v0.x``. For more advanced functionality and additional types, enabling ``v1`` is recommended. It forms the basis for more complex cases and will evolve into the standard model for Dataclass Wizard. For more info, see the `Field Guide to V1 Opt-in `_. Special Cases ------------- .. note:: With most annotated Python types, it is clear and unambiguous how they are to be loaded from JSON, or dumped when they are serialized back to JSON. However, here a few special cases that are worth going over. * ``str`` - Converts inputs to strings. If already a string, it remains unchanged. Non-strings are converted to their string representation. By default in **v1**, ``None`` is converted using ``str(None)`` (i.e. ``'None'``) for ``str`` fields, and preserved as ``None`` for ``Optional[str]`` fields. Set ``Meta.v1_coerce_none_to_empty_str = True`` to coerce ``None`` to ``''`` instead. *Examples*: ``123`` → ``'123'``, ``None`` → ``'None'`` (or ``''`` with opt-in) * ``bool`` - JSON values that appear as strings or integers will be de-serialized to a ``bool`` using a case-insensitive search that matches against the following "truthy" values: *TRUE, T, YES, Y, ON, 1* * ``int`` - Converts valid inputs to integers: - String representations of integers (e.g., ``"123"``). - Floats or float strings with or without fractional parts (e.g., ``123.4`` or ``"123.4"``), rounded to the nearest integer. - Empty strings or ``None`` return the default value of ``0``. .. warning:: Starting in v1.0, floats or float strings with fractional parts (e.g., ``123.4`` or ``"123.4"``) will raise an error instead of being rounded. * ``Enum`` - JSON values (ideally strings) are de-serialized to ``Enum`` subclasses via the ``value`` attribute, and are serialized back to JSON using the same ``value`` attribute. * ``UUID`` types are de-serialized from JSON strings using the constructor method -- i.e. ``UUID(string)``, and by default are serialized back to JSON using the ``hex`` attribute -- i.e. :attr:`my_uuid.hex`. * ``Decimal`` types are de-serialized using the ``Decimal(str(o))`` syntax -- or via an annotated subclass of *Decimal* -- and are serialized via the builtin :func:`str` function. * ``NamedTuple`` sub-types are de-serialized from a ``list``, ``tuple``, or any iterable type into the annotated sub-type. They are serialized back as the the annotated ``NamedTuple`` sub-type; this is mainly because *named tuples* are essentially just tuples, so they are inherently JSON serializable to begin with. * For ``date``, ``time``, and ``datetime`` types, string values are de-serialized using the builtin :meth:`fromisoformat` method; for ``datetime`` and ``time`` types, a suffix of "Z" appearing in the string is first replaced with "+00:00", which represents UTC time. JSON values for ``datetime`` and ``date`` annotated types appearing as numbers will be de-serialized using the builtin :meth:`fromtimestamp` method. All these types are serialized back to JSON using the builtin :meth:`isoformat` method. For ``datetime`` and ``time`` types, there is one noteworthy addition: the suffix "+00:00" is replaced with "Z", which is a common abbreviation for UTC time. * For ``timedelta`` types, the values to de-serialize can either be strings or numbers, so we check the type explicitly. If the value is a string, we first ensure it's in a numeric form like '1.23', and if so convert it to a *float* value in seconds; otherwise, we convert values like '01:45' or '3hr12m56s' via the `pytimeparse`_ module, which is also available as an extra via ``pip install dataclass-wizard[timedelta]``. Lastly, any numeric values are assumed to be in seconds and are used as is. All :class:`timedelta` values are serialized back to JSON using the builtin :meth:`str` method, so for example ``timedelta(seconds=3)`` will be serialized as "0:00:03". * ``set``, ``frozenset``, and ``deque`` types will be de-serialized using their annotated base types, and serialized as ``list``'s. * Commonly used ``dict`` sub-types (such as ``defaultdict``) will be de-serialized from JSON objects using the annotated base type, and serialized back as plain ``dict`` objects. Extending Supported Types ~~~~~~~~~~~~~~~~~~~~~~~~ If a type is not supported out of the box, you can extend Dataclass Wizard using **custom type hooks**. Type hooks allow you to define how a type is loaded and dumped, without modifying the type itself. See :doc:`advanced_usage/type_hooks` for more information. .. _using dataclasses: https://dcw.ritviknag.com/en/latest/common_use_cases/dataclasses_in_union_types.html .. _pytimeparse: https://pypi.org/project/pytimeparse/