# Custom type mapping

When managing a big collection of models, it sometimes is tricky to split them into multiple python modules. Even more so if they depend on each other. For the models to be serializable by xsdata, they need to be able to import all other referenced models, which might not be possible due to circular imports.

One solution to get around this problem is to fence the imports within the python modules by using `typing.TYPE_CHECKING` and passing a dedicated type-map dictionary to the `SerializerConfig`.

city.py

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

    if TYPE_CHECKING:
        from tests.models.typemapping.street import Street

    @dataclass
    class City:
        class Meta:
            global_type = False

        name: str
        streets: List["Street"] = field(default_factory=list)

street.py

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

    if TYPE_CHECKING:
        from tests.models.typemapping.city import City
        from tests.models.typemapping.house import House

    @dataclass
    class Street:
        class Meta:
            global_type = False

        name: str
        city: Optional["City"] = None
        houses: List["House"] = field(default_factory=list)

house.py

    from dataclasses import dataclass
    from typing import TYPE_CHECKING, Optional

    if TYPE_CHECKING:
        from tests.models.typemapping.street import Street

    @dataclass
    class House:
        class Meta:
            global_type = False

        number: int
        street: Optional["Street"] = None

By fencing the imports, we are able to keep our models in different python modules that are cleanly importable and considered valid by static type checkers.

Passing the type-map dictionary, which maps the class/model-names directly to imported objects, enables xsdata to serialize the models.

    from xsdata.formats.dataclass.serializers import XmlSerializer
    from xsdata.formats.dataclass.serializers.config import SerializerConfig

    from tests.models.typemapping.city import City
    from tests.models.typemapping.house import House
    from tests.models.typemapping.street import Street

    city1 = City(name="footown")
    street1 = Street(name="foostreet")
    house1 = House(number=23)
    city1.streets.append(street1)
    street1.houses.append(house1)

    type_map = {"City": City, "Street": Street, "House": House}
    serializer_config = SerializerConfig(pretty_print=True, globalns=type_map)

    xml_serializer = XmlSerializer(config=serializer_config)
    serialized_house = xml_serializer.render(city1)
    print(serialized_house)

    <?xml version="1.0" encoding="UTF-8"?>
    <City>
      <name>footown</name>
      <streets>
        <name>foostreet</name>
        <houses>
          <number>23</number>
        </houses>
      </streets>
    </City>