Skip to content

Types

Important

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.

Collections

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

List

typing.List

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})

Tuple

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

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

Dict

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"})

Union

typing.Union

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.

Boolean

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

Decimal

Python Type: decimal.Decimal

XML Type: decimal

Float

Python Type: float

XML Types: double, float

Integer

Python Type: int

XML Types:

Object

Python Type: object

XML Type: anySimpleType

QName

Python Type: xml.etree.ElementTree.QName

XML Types: QName, NOTATION

String

Python Type: str

XML Types:

XmlDate

Python Type: xsdata.models.datatype.XmlDate

XML Type: date

XmlDateTime

Python Type: xsdata.models.datatype.XmlDateTime

XML Types: dateTime, dateTimeStamp

XmlDuration

Python Type: xsdata.models.datatype.XmlDuration

XML Types:

XmlPeriod

Python Type: xsdata.models.datatype.XmlPeriod

XML Types:

XmlTime

Python Type: xsdata.models.datatype.XmlTime

XML Type:: time

Enum

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)
<Example>
  <good>10.98</good>
  <bad>-9.9827632</bad>
</Example>
>>> 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))
<DateTimeObject>2023-11-24T10:38:56.123</DateTimeObject>
>>>
>>>
>>> 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.day}-{value.month}-{value.year}"
...                 f"T{value.hour}:{value.minute}:{value.second}"
...             )
...
...
>>> converter.register_converter(XmlDateTime, MyXmlDateTimeConverter())
>>> print(serializer.render(datetime_obj))
<DateTimeObject>24-11-2023T10:38:56</DateTimeObject>
>>>
>>> converter.unregister_converter(XmlDateTime)