Skip to main content

Marshal dataclasses to/from JSON and Python dict objects, and add support for properties with default values.

Project description

Dataclass Wizard

https://img.shields.io/pypi/v/dataclass-wizard.svg https://img.shields.io/pypi/pyversions/dataclass-wizard.svg https://travis-ci.com/rnag/dataclass-wizard.svg?branch=main Documentation Status Updates

This library provides a set of simple, yet elegant wizarding tools for interacting with the Python dataclasses module.

Full documentation is at:

Features

Here are the supported features that dataclass-wizard currently provides:

  • JSON (de)serialization: marshal dataclasses to/from JSON and Python dict objects.

  • Field properties: support for using properties with default values in dataclass instances.

Usage

Using the built-in JSON marshalling support for dataclasses:

from dataclasses import dataclass, field
from typing import Optional, List

from dataclass_wizard import JSONSerializable


@dataclass
class MyClass(JSONSerializable):

    my_str: Optional[str]
    list_of_int: List[int] = field(default_factory=list)
    is_active: bool = False


string = """{"my_str": 20, "ListOfInt": ["1", "2", 3], "isActive": "true"}"""
c = MyClass.from_json(string)
print(repr(c))
# prints:
#   MySampleClass(my_str='20', list_of_int=[1, 2, 3], is_active=True)

print(c.to_json())
# prints:
#   {"myStr": "20", "listOfInt": [1, 2, 3], "isActive": true}

… and with the property_wizard, which provides supports for field properties with default values in dataclasses:

from dataclasses import dataclass
from typing import Union

from dataclass_wizard import property_wizard


@dataclass
class Vehicle(metaclass=property_wizard):

    # Note: The example below uses the default value for the annotated type
    # (0 here, because `int` appears first). The right-hand value assigned to
    # `wheels` is ignored, as it is simply re-declared by the property. To
    # specify a default value of 4, comment out the `wheels` field and
    # replace it with the `_wheels` declaration below.
    #   _wheels: Union[int, str] = 4
    wheels: Union[int, str] = 0

    @property
    def wheels(self) -> int:
        return self._wheels

    @wheels.setter
    def wheels(self, wheels: Union[int, str]):
        self._wheels = int(wheels)


if __name__ == '__main__':
    v = Vehicle()
    print(v)
    # prints:
    #   Vehicle(wheels=0)

    v = Vehicle(wheels=3)
    print(v)
    # prints:
    #   Vehicle(wheels=3)

    v = Vehicle('6')
    print(v)
    # prints:
    #   Vehicle(wheels=6)

    assert v.wheels == 6, 'The constructor should use our setter method'

    # Confirm that we go through our setter method
    v.wheels = '123'
    assert v.wheels == 123

Installing Dataclass Wizard and Supported Versions

The Dataclass Wizard library is available on PyPI:

$ python -m pip install dataclass-wizard

The dataclass-wizard library officially supports Python 3.6 or higher.

JSON Marshalling

JSONSerializable is a Mixin class which provides the following helper methods that are useful for loading (and serializing) a dataclass to JSON, as defined by the AbstractJSONWizard interface.

Method

Example

Description

from_json

item = Product.from_json(string)

Converts a JSON string to an instance of the dataclass, or a list of the dataclass instances.

from_list

list_of_item = Product.from_list(l)

Converts a Python list object to a list of the dataclass instances.

from_dict

item = Product.from_dict(d)

Converts a Python dict object to an instance of the dataclass.

to_dict

d = item.to_dict()

Converts the dataclass instance to a Python dict object that is JSON serializable.

to_json

string = item.to_json()

Converts the dataclass instance to a JSON string representation.

Additionally, it implements a __str__ method, which will pretty print the JSON representation of an object; this is quite useful for debugging purposes. Whenever you invoke print(obj) or str(obj), for example, it’ll invoke this method which will pretty print the dataclass object.

Note that the __repr__ method, which is implemented by the dataclass decorator, is also available. To invoke the Python object representation of the dataclass instance, you can instead use repr(obj) or f'{obj!r}'.

To mark a dataclass instance as being JSON serializable (and de-serializable), simply sub-class from JSONSerializable as shown below. You can also extend from the class alias JSONWizard, if you prefer to use that instead.

Here is a (more) complete example of using the JSONSerializable Mixin class:

from dataclasses import dataclass
from datetime import datetime
from typing import Optional, List, Literal, Union, Dict, Any, NamedTuple

from dataclass_wizard import JSONSerializable


@dataclass
class MyTestClass(JSONSerializable):
    my_ledger: Dict[str, Any]
    the_answer_to_life: Optional[int]
    people: List['Person']
    is_enabled: bool = True


@dataclass
class Person:
    name: 'Name'
    age: int
    birthdate: datetime
    gender: Literal['M', 'F', 'N/A']
    occupation: Union[str, List[str]]
    details: Optional[str] = None


class Name(NamedTuple):
    """A person's name"""
    first: str
    last: str
    salutation: Optional[Literal['Mr.', 'Mrs.', 'Ms.', 'Dr.']] = 'Mr.'


data = {
    'myLedger': {
        'Day 1': 'some details',
        'Day 17': ['a', 'sample', 'list']
    },
    'theAnswerTOLife': '42',
    'People': [
        {
            'name': ('Roberto', 'Fuirron'),
            'age': 21,
            'birthdate': '1950-02-28T17:35:20Z',
            'gender': 'M',
            'occupation': ['sailor', 'fisher'],
            'details': 'My sample details here'
        },
        {
            'name': ('Janice', 'Darr', 'Dr.'),
            'age': 45,
            'birthdate': '1971-11-05 05:10:59',
            'gender': 'F',
            'occupation': 'Dentist'
        }
    ]
}

c = MyTestClass.from_dict(data)

print(repr(c))
# prints the following result on a single line:
#   MyTestClass(
#       my_ledger={'Day 1': 'some details', 'Day 17': ['a', 'sample', 'list']},
#       the_answer_to_life=42,
#       people=[
#           Person(
#               name=Name(first='Roberto', last='Fuirron', salutation='Mr.'),
#               age=21, birthdate=datetime.datetime(1950, 2, 28, 17, 35, 20, tzinfo=datetime.timezone.utc),
#               gender='M', occupation=['sailor', 'fisher'], details='My sample details here'
#           ),
#           Person(
#               name=Name(first='Janice', last='Darr', salutation='Dr.'),
#               age=45, birthdate=datetime.datetime(1971, 11, 5, 5, 10, 59),
#               gender='F', occupation='Dentist', details=None
#           )
#       ], is_enabled=True)

# calling `print` on the object invokes the `__str__` method, which will
# pretty-print the JSON representation of the object by default. You can
# also call the `to_json` method to print the JSON string on a single line.

print(c)
# prints:
#     {
#       "myLedger": {
#         "Day 1": "some details",
#         "Day 17": [
#           "a",
#           "sample",
#           "list"
#         ]
#       },
#       "theAnswerToLife": 42,
#       "people": [
#         {
#           "name": [
#             "Roberto",
#             "Fuirron",
#             "Mr."
#           ],
#           "age": 21,
#           "birthdate": "1950-02-28T17:35:20Z",
#           "gender": "M",
#           "occupation": [
#             "sailor",
#             "fisher"
#           ],
#           "details": "My sample details here"
#         },
#         {
#           "name": [
#             "Janice",
#             "Darr",
#             "Dr."
#           ],
#           "age": 45,
#           "birthdate": "1971-11-05T05:10:59",
#           "gender": "F",
#           "occupation": "Dentist",
#           "details": null
#         }
#       ],
#       "isEnabled": true
#     }

Field Properties

The Python dataclasses library has some key limitations with how it currently handles properties and default values.

The dataclass-wizard package natively provides support for using field properties with default values in dataclasses. The main use case here is to assign an initial value to the field property, if one is not explicitly passed in via the constructor method.

To use it, simply import the property_wizard helper function, and add it as a metaclass on any dataclass where you would benefit from using field properties with default values. The metaclass also pairs well with the JSONSerializable mixin class.

For more examples and important how-to’s on properties with default values, refer to the Using Field Properties section in the documentation.

Credits

This package was created with Cookiecutter and the rnag/cookiecutter-pypackage project template.

History

0.2.4 (2021-08-04)

  • Update README docs

    • Move the section on Advanced Usage to the main docs

    • Cleanup usage and docs in the Field Properties section

0.2.3 (2021-08-03)

  • Add better keywords for the package

0.2.2 (2021-08-03)

  • Explicitly add a dependency on typing-extensions for Python 3.6 and 3.7

0.2.1 (2021-08-03)

  • Fix a bug for Python 3.6 where the build failed when using the PyForwardRef annotation.

0.2.0 (2021-08-03)

  • Rename type variable EXPLICIT_NULL to ExplicitNull

  • Rename module type_defs.py to type_def.py

  • Rename module base_meta.py to bases_meta.py

  • JSONSerializable.Meta: rename attribute date_time_with_dump to marshal_date_time_as, as I believe this name is overall more clearer.

  • Refactor the property_wizard helper function and update it to cover some edges cases.

  • Add test cases to confirm intended functionality of property_wizard.

0.1.0 (2021-08-02)

  • First release on PyPI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dataclass-wizard-0.2.4.tar.gz (47.5 kB view details)

Uploaded Source

Built Distribution

dataclass_wizard-0.2.4-py2.py3-none-any.whl (36.3 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file dataclass-wizard-0.2.4.tar.gz.

File metadata

  • Download URL: dataclass-wizard-0.2.4.tar.gz
  • Upload date:
  • Size: 47.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.3 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.0 CPython/3.8.7

File hashes

Hashes for dataclass-wizard-0.2.4.tar.gz
Algorithm Hash digest
SHA256 1b4fbb6c3ce19704266c084551f0c391aa5f2fb2e99bb0898997846b3fcd3ed3
MD5 00e900cf47434c6a2ce7a14ef3a717cf
BLAKE2b-256 c063c30183a7056772e69475009211e15a4a7a4e11d9237cfe209f1973efa845

See more details on using hashes here.

File details

Details for the file dataclass_wizard-0.2.4-py2.py3-none-any.whl.

File metadata

  • Download URL: dataclass_wizard-0.2.4-py2.py3-none-any.whl
  • Upload date:
  • Size: 36.3 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.3 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.0 CPython/3.8.7

File hashes

Hashes for dataclass_wizard-0.2.4-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 9e54ced091b5f87439a7f0744c4d8f9f11396f0d001bf373bd23411dc406140d
MD5 0a6eb3a078d4d979aabbaf01892a97df
BLAKE2b-256 64d2046e133f8e35969797b89afe771c55da1c58ff86ba9657ef6ef29accd4db

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page