Recursive models

Given the following simple classes together with their mappings, you can build more powerful recusive mappings.

>>> @dataclass
... class Person:
...     name: str
...     age: int
>>>
>>> @mapper(Person, {"age": lambda: 45, "name": lambda self: f"{self.first_name} {self.surname}"})
... @dataclass
... class Contact:
...     surname: str
...     first_name: str
>>>
>>> @dataclass
... class Item:
...     description: str
...     cnt: int
>>>
>>> @mapper(Item, {"description": "name"})
... @dataclass
... class OrderItem:
...     name: str
...     cnt: int

Here the dataclasses use other dataclasses as fields, either direct recipient: Contact (and recipient: Person), or even inside a list items: List[OrderItem] (and items: List[Item]) or in dictionary values items_by_name: dict[str, OrderItem] (and items_by_name: dict[str, Item]). As there is a mapper defined from Contact to Person, and also a mapper defined from OrderItem to Item, the object custom_order can be recusively mapped.

>>> @dataclass
... class Order:
...     recipient: Person
...     items: List[Item]
...     items_by_name: Dict[str, Item]
>>>
>>> @mapper(Order)
... @dataclass
... class CustomOrder:
...     recipient: Contact
...     items: List[OrderItem]
...     items_by_name: Dict[str, OrderItem]
>>>
>>> custom_order = CustomOrder(
...     recipient=Contact(first_name="Barbara E.", surname="Rolfe"),
...     items=[OrderItem(name="fruit", cnt=3), OrderItem(name="sweets", cnt=5)],
...     items_by_name={"fruit": OrderItem(name="fruit", cnt=3), "sweets": OrderItem(name="sweets", cnt=5)}
... )
>>> map_to(custom_order, Order) 
Order(recipient=Person(name='Barbara E. Rolfe', age=45),
      items=[Item(description='fruit', cnt=3), Item(description='sweets', cnt=5)],
      items_by_name={'fruit': Item(description='fruit', cnt=3), 'sweets': Item(description='sweets', cnt=5)})

Warning

At the moment it’s not possible to create cyclic mappings.