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