Skip to content



Dataclasses don't validate values when creating a new instances or assigning values to fields. Automatic conversion of values to appropriate python data types occurs only during the parsing process.

The parser handles value/type discrepancies leniently, potentially ignoring the defined field type hint. When such an error arises, the converter issues a ConverterWarning.

If you prefer to treat conversion warnings as exceptions you need to activate the ParserConfig.fail_on_converter_warnings option.


PEP-585 type hinting generics in standard collections are also supported.



Case Example
List value: List[str] = field(default_factory=list)
Optional List value: Optional[List[str]] = field(default=None)
List Union value: List[Union[str, int]] = field(default_factory=list)
Tokens List value: List[str] = field(default_factory=list, metadata={"tokens": True})
List of Tokens value: List[List[str]] = field(default_factory=list, metadata={"tokens": True})


typing.Tuple can be use in frozen dataclasses, for immutable instances.

Case Example
Tuple value: Tuple[str] = field(default_factory=list)
Optional Tuple value: Optional[Tuple[str]] = field(default=None)
Tuple Union value: Tuple[Union[str, int]] = field(default_factory=list)
Tokens Tuple value: Tuple[str] = field(default_factory=list, metadata={"tokens": True})
Tuple of Tokens value: Tuple[Tuple[str]] = field(default_factory=list, metadata={"tokens": True})


typing.Dict is reserved for Attributes type fields to capture any undefined attribute.

Case Example
Attributes attrs: Dict[str, str] = field(default_factory=dict, metadata={"type": "Attributes"})



Case Example
Union value: Union[str, int, float] = field()
Optional Union value: Optional[Union[str, int, float]] = field(default=None)

The order of the types doesn't matter, internally the converter sorts the types by priority:

  1. int
  2. bool
  3. float
  4. Decimal
  5. datetime
  6. date
  7. time
  8. XmlTime
  9. XmlDate
  10. XmlDateTime
  11. XmlDuration
  12. XmlPeriod
  13. QName
  14. str

Standard Types

This is the list of all the supported primitive types.


Input Python XML JSON
"true" True "true" true
"1" True "true" true
"false" False "false" false
"1" False "false" false

Python Type: bool

XML Type: boolean

Bytes Array

The fields must provide the format metadata property.

  • base16 for hexadecimal string
  • base64 for base64 encoded bytes-like object or ASCII strings

Python Type: bytes

XML Types: hexBinary, base64Binary


Python Type: decimal.Decimal

XML Type: decimal


Python Type: float

XML Types: double, float


Python Type: int

XML Types:


Python Type: object

XML Type: anySimpleType


Python Type: xml.etree.ElementTree.QName



Python Type: str

XML Types:


Python Type: xsdata.models.datatype.XmlDate

XML Type: date


Python Type: xsdata.models.datatype.XmlDateTime

XML Types: dateTime, dateTimeStamp


Python Type: xsdata.models.datatype.XmlDuration

XML Types:


Python Type: xsdata.models.datatype.XmlPeriod

XML Types:


Python Type: xsdata.models.datatype.XmlTime

XML Type:: time


Python Type: enum.Enum

XML Type:: enumeration

User Types

You can register your own custom types as well as long as they are not dataclasses.

>>> from dataclasses import dataclass, field
>>> from xsdata.formats.converter import Converter, converter
>>> from xsdata.formats.dataclass.parsers import XmlParser
>>> from xsdata.formats.dataclass.serializers import XmlSerializer
>>> serializer = XmlSerializer()
>>> serializer.config.indent = "  "
>>> serializer.config.xml_declaration = False
>>> class TheGoodFloat(float):
...     pass
>>> @dataclass
... class Example:
...     good: TheGoodFloat = field(metadata=dict(format="{:.2f}"))
...     bad: float
>>> class TheGoodFloatConverter(Converter):
...    def deserialize(self, value: str, **kwargs) -> TheGoodFloat:
...        return round(TheGoodFloat(value), 1)  # Even nicer
...    def serialize(self, value: TheGoodFloat, **kwargs) -> str:
...        if kwargs["format"]:
...            return kwargs["format"].format(value)
...        return str(value)
>>> converter.register_converter(TheGoodFloat, TheGoodFloatConverter())
>>> output = serializer.render(Example(TheGoodFloat(10.983263748), -9.9827632))
>>> print(output)
>>> XmlParser().from_string(output)
Example(good=11.0, bad=-9.9827632)

Overriding standard type converters

It is also possible to override the converter for any of the standard types. For example, we can override the standard serialize function for XmlDateTime.

>>> from dataclasses import dataclass
>>> from typing import Any, Optional
>>> from xsdata.formats.converter import Converter, converter
>>> from xsdata.formats.dataclass.parsers import XmlParser
>>> from xsdata.formats.dataclass.serializers import XmlSerializer
>>> from xsdata.formats.dataclass.serializers.config import SerializerConfig
>>> from xsdata.models.datatype import XmlDateTime
>>> serializer = XmlSerializer(config=SerializerConfig(xml_declaration=False))
>>> @dataclass
... class DateTimeObject:
...     datetime: XmlDateTime
>>> datetime_obj = DateTimeObject(
...     datetime=XmlDateTime(
...         year=2023,
...         month=11,
...         day=24,
...         hour=10,
...         minute=38,
...         second=56,
...         fractional_second=123_000_000,
...     )
... )
>>> print(serializer.render(datetime_obj))
>>> class MyXmlDateTimeConverter(Converter):
...     def deserialize(self, value: Any, **kwargs: Any) -> XmlDateTime:
...         return XmlDateTime.from_string(value)
...     def serialize(self, value: Any, **kwargs: Any) -> Optional[str]:
...         if isinstance(value, XmlDateTime):
...             # Can be anything you like
...             return (
...                 f"{}-{value.month}-{value.year}"
...                 f"T{value.hour}:{value.minute}:{value.second}"
...             )
>>> converter.register_converter(XmlDateTime, MyXmlDateTimeConverter())
>>> print(serializer.render(datetime_obj))
>>> converter.unregister_converter(XmlDateTime)