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
PEP-604 union types as X | Y are also supported.
| 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:
intboolfloatDecimaldatetimedatetimeXmlTimeXmlDateXmlDateTimeXmlDurationXmlPeriodQNamestr
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.
base16for hexadecimal stringbase64for 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][]
Integer
Python Type: [int][]
XML Types:
- int
- nonPositiveInteger
- negativeInteger
- long
- integer
- short
- byte
- nonNegativeInteger
- unsignedLong
- unsignedInt
- unsignedShort
- unsignedByte
- positiveInteger
Object
Python Type: [object][]
XML Type: anySimpleType
QName
Python Type: [xml.etree.ElementTree.QName][]
String
Python Type: [str][]
XML Types:
- string
- anyURI
- normalizedString
- token
- language
- NMTOKEN
- NMTOKENS
- Name
- NCName
- ID
- IDREF
- IDREFS
- ENTITIES
- ENTITY
- anyAtomicType
- error
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)