File: v1_alias.rst

package info (click to toggle)
dataclass-wizard 0.35.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,808 kB
  • sloc: python: 15,276; makefile: 111; javascript: 23
file content (207 lines) | stat: -rw-r--r-- 6,234 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
.. currentmodule:: dataclass_wizard.v1
.. title:: Alias in V1 (v0.35.0+)

Alias in V1 (``v0.35.0+``)
==========================

.. tip::

    The following documentation introduces support for :func:`Alias` and :func:`AliasPath`
    added in ``v0.35.0``. This feature is part of an experimental "V1 Opt-in" mode,
    detailed in the `Field Guide to V1 Opt-in`_.

    V1 features are available starting from ``v0.33.0``. See `Enabling V1 Experimental Features`_ for more details.

    :func:`Alias` and :func:`AliasPath` provide mechanisms to map JSON keys or nested paths to dataclass fields, enhancing serialization
    and deserialization in the ``dataclass-wizard`` library. These utilities build upon Python's :func:`dataclasses.field`, enabling
    custom mappings for more flexible and powerful data handling.

An alias is an alternative name for a field, used when de/serializing data. This feature is introduced in **v0.35.0**.

You can specify an alias in the following ways:

* Using :func:`Alias` and passing alias(es) to ``all``, ``load``, or ``dump``

* Using ``Meta`` setting ``v1_field_to_alias``

For examples of how to use ``all``, ``load``, and ``dump``, see `Field Aliases`_.

Field Aliases
-------------

Field aliases allow mapping one or more JSON key names to a dataclass field for de/serialization. This feature
provides flexibility when working with JSON structures that may not directly match your Python dataclass definitions.

Defining Aliases
~~~~~~~~~~~~~~~~

There are three primary ways to define an alias:

* **Single alias for all operations**
    * ``Alias('foo')``

* **Separate aliases for de/serialization**
    * ``Alias(load='foo')`` for de-serialization
    * ``Alias(dump='foo')`` for serialization

The ``load`` and ``dump`` parameters enable fine-grained control over how fields are handled
during deserialization and serialization, respectively. If both are provided, the field can
behave differently depending on the operation.

Examples of Field Aliases
~~~~~~~~~~~~~~~~~~~~~~~~~

Using a Single Alias
^^^^^^^^^^^^^^^^^^^^

You can use a single alias for both serialization and deserialization by passing the alias name directly to :func:`Alias`:

.. code-block:: python3

    from dataclasses import dataclass

    from dataclass_wizard import JSONPyWizard
    from dataclass_wizard.v1 import Alias


    @dataclass
    class User(JSONPyWizard):
        class _(JSONPyWizard.Meta):
            v1 = True

        name: str = Alias('username')


    user = User.from_dict({'username': 'johndoe'})
    print(user)
    # > User(name='johndoe')
    print(user.to_dict())
    # > {'username': 'johndoe'}

Using Separate Aliases for Serialization and Deserialization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To define distinct aliases for `load` and `dump` operations:

.. code-block:: python3

    from dataclasses import dataclass

    from dataclass_wizard import JSONPyWizard
    from dataclass_wizard.v1 import Alias


    @dataclass
    class User(JSONPyWizard):
        class _(JSONPyWizard.Meta):
            v1 = True

        name: str = Alias(load='username', dump='user_name')


    user = User.from_dict({'username': 'johndoe'})
    print(user)
    # > User(name='johndoe')
    print(user.to_dict())
    # > {'user_name': 'johndoe'}

Skipping Fields During Serialization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To exclude a field during serialization, use the ``skip`` parameter:

.. code-block:: python3

    from dataclasses import dataclass

    from dataclass_wizard import JSONPyWizard
    from dataclass_wizard.v1 import Alias


    @dataclass
    class User(JSONPyWizard):
        class _(JSONPyWizard.Meta):
            v1 = True

        name: str = Alias('username', skip=True)


    user = User.from_dict({'username': 'johndoe'})
    print(user.to_dict())  # > {}

Advanced Usage
^^^^^^^^^^^^^^

Aliases can be combined with :obj:`typing.Annotated` to support complex scenarios. You can also use the ``v1_field_to_alias`` meta-setting
for bulk aliasing:

.. code-block:: python3

    from dataclasses import dataclass
    from typing import Annotated
    from dataclass_wizard import JSONPyWizard
    from dataclass_wizard.v1 import Alias


    @dataclass
    class Test(JSONPyWizard):
        class _(JSONPyWizard.Meta):
            v1 = True
            v1_key_case = 'CAMEL'
            v1_field_to_alias = {
                'my_int': 'MyInt',
                '__load__': False,
            }

        my_str: str = Alias(load=('a_str', 'other_str'))
        my_bool_test: Annotated[bool, Alias(dump='myDumpedBool')]
        my_int: int
        other_int: int = Alias(dump='DumpedInt')


    t = Test.from_dict({'other_str': 'test', 'myBoolTest': 'T', 'myInt': '123', 'otherInt': 321.0})
    print(t.to_dict())
    # > {'my_str': 'test', 'myDumpedBool': True, 'MyInt': 123, 'DumpedInt': 321}

Alias Paths
-----------

Maps one or more nested JSON paths to a dataclass field. See documentation on :func:`AliasPath` for more details.

**Examples**

Mapping multiple nested paths to a field::

    from dataclasses import dataclass
    from dataclass_wizard import fromdict, LoadMeta
    from dataclass_wizard.v1 import AliasPath

    @dataclass
    class Example:
        my_str: str = AliasPath('a.b.c.1', 'x.y["-1"].z', default="default_value")

    LoadMeta(v1=True).bind_to(Example)

    print(fromdict(Example, {'x': {'y': {'-1': {'z': 'some_value'}}}}))
    # > Example(my_str='some_value')

Using :obj:`typing.Annotated` with nested paths::

    from dataclasses import dataclass
    from typing import Annotated
    from dataclass_wizard import JSONPyWizard
    from dataclass_wizard.v1 import AliasPath

    @dataclass
    class Example(JSONPyWizard):
        class _(JSONPyWizard.Meta):
            v1 = True

        my_str: Annotated[str, AliasPath('my."7".nested.path.-321')]

    ex = Example.from_dict({'my': {'7': {'nested': {'path': {-321: 'Test'}}}}})
    print(ex)  # > Example(my_str='Test')


.. _`Enabling V1 Experimental Features`: https://github.com/rnag/dataclass-wizard/wiki/V1:-Enabling-Experimental-Features
.. _`Field Guide to V1 Opt-in`: https://github.com/rnag/dataclass-wizard/wiki/Field-Guide-to-V1-Opt%E2%80%90in