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:
int
bool
float
Decimal
datetime
date
time
XmlTime
XmlDate
XmlDateTime
XmlDuration
XmlPeriod
QName
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 stringbase64
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
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)