Backends
Added in version 2.0.
Django-modern-rpc can be configured to use different backends to deserialize incoming RPC requests and serialize response data into the correct RPC response format. Using a custom backend can help implement non-standard behavior (for example, allowing serialization of additional types) or improve performance.
To compare backend performance, django-modern-rpc provides a benchmark test suite that is automatically run on GitHub Actions for each commit.
Terminology
Deserializer
In each backend, the Deserializer class parses the incoming request body (XML or JSON) using its underlying library
and converts it into a valid Python representation. When the body is not syntactically correct, the deserialization
process will usually raise an RPCParseError.
The result will be passed to the Unmarshaller (see below).
Unmarshaller
The Unmarshaller class takes a Python dictionary built from the incoming request body and extracts important information, such as the procedure name to call and the provided arguments.
When the format (XML-RPC or JSON-RPC) of the parsed request is invalid, the Unmarshaller will usually raise an
RPCInvalidRequest.
Marshaller
The Marshaller class builds a high-level object representing the result of a procedure call (either success or error).
This object is then passed to the Serializer, which converts it to a string representation ready to be returned in an
HttpResponse instance.
When the procedure response contains invalid data, the Marshaller will usually raise an RPCMarshallingError
Serializer
The Serializer uses its underlying library to serialize the response built by the Marshaller into a valid string representation.
When the serialization process fails, an RPCMarshallingError may be raised.
Configuration
For each protocol (XML-RPC, JSON-RPC), a different class can be configured for deserialization and serialization.
The default values are:
MODERNRPC_XML_DESERIALIZER = {
"class": "modernrpc.xmlrpc.backends.xmlrpc.PythonXmlRpcDeserializer",
"kwargs": {}
}
MODERNRPC_XML_SERIALIZER = {
"class": "modernrpc.xmlrpc.backends.xmlrpc.PythonXmlRpcSerializer",
"kwargs": {}
}
MODERNRPC_JSON_DESERIALIZER = {
"class": "modernrpc.jsonrpc.backends.json.PythonJsonDeserializer",
"kwargs": {}
}
MODERNRPC_JSON_SERIALIZER = {
"class": "modernrpc.jsonrpc.backends.json.PythonJsonSerializer",
"kwargs": {}
}
Each class can be configured using the kwargs dictionary. The valid parameters depend on the selected backend.
Some arguments are common across many backends, while others apply only to specific ones. See below for a detailed
explanation of each backend’s configuration.
Some backends may be configured to use a different Unmarshaller and/or Marshaller class. When this is possible, use
unmarshaller_klass / unmarshaller_kwargs and marshaller_klass / marshaller_kwargs in kwargs.
XML-RPC backends
xmlrpc (python builtin)
This is the most basic backend that depends on Python’s builtin xmlrpc module. It is used by default for both deserialization and serialization of XML-RPC requests and responses.
Pros / Cons
RPCInvalidRequest if the method name cannot
be determined (for example, when the root tag is not methodCall).Configuration
Unmarshaller / Deserializer
load_kwargs: passed toxmlrpc.client.loads. See the xmlrpc.client.loads() documentation for the list of valid keyword arguments
MODERNRPC_XML_DESERIALIZER = {
"class": "modernrpc.xmlrpc.backends.xmlrpc.PythonXmlRpcDeserializer",
"kwargs": {
"load_kwargs": {"use_datetime": False, "use_builtin_types": False}
}
}
The Unmarshaller class cannot be changed or configured at the moment.
Marshaller / Serializer
dump_kwargs: passed toxmlrpc.client.dumps. See the xmlrpc.client.dumps() documentation for the list of valid keywords arguments.
MODERNRPC_XML_SERIALIZER = {
"class": "modernrpc.xmlrpc.backends.xmlrpc.PythonXmlRpcSerializer",
"kwargs": {
"dump_kwargs": {"allow_none": False}
}
}
The Marshaller class cannot be changed or configured at the moment.
etree (xml.etree.ElementTree)
Uses Python’s standard library xml.etree.ElementTree (through defusedxml wrappers) to parse and build XML-RPC
messages. Can be used as both serializer and deserializer.
Pros / Cons
Configuration
Unmarshaller / Deserializer
unmarshaller_klass: dotted path to the Unmarshaller class. Defaults tomodernrpc.xmlrpc.backends.marshalling.EtreeElementUnmarshaller.unmarshaller_kwargs: keyword arguments passed to the Unmarshaller. Supported option:allow_none(default:True): whether to allow parsing of<nil/>/Nonevalues.
element_type_klass: dotted path to the XML Element class used to specialize the generic unmarshaller. Defaults toxml.etree.ElementTree.Element.load_kwargs: passed todefusedxml.ElementTree.XML. By default,forbid_dtdis set toTruefor safety.
Example:
Marshaller / Serializer
marshaller_klass: dotted path to the Marshaller class. Defaults tomodernrpc.xmlrpc.backends.marshalling.EtreeElementMarshaller.marshaller_kwargs: keyword arguments passed to the Marshaller. Supported options:allow_none(default:True): whether to allow serialization ofNonevalues.element_factory(default:xml.etree.ElementTree.Element): the function used to build a new Elementsub_element_factory(default:xml.etree.ElementTree.SubElement): the function used to build a new SubElement
element_type_klass: dotted path to the XML Element class used to specialize the generic marshaller. Defaults toxml.etree.ElementTree.Element.dump_kwargs: passed todefusedxml.ElementTree.tostring.
Example:
lxml
Uses third-party lxml library (lxml.etree). Can be used as both serializer and deserializer.
To use this backend, lxml must be installed in the current environment. An extra dependency can be used for that:
pip install django-modern-rpc[lxml]
poetry add django-modern-rpc[lxml]
uv add django-modern-rpc[lxml]
Pros / Cons
Configuration
Unmarshaller / Deserializer
unmarshaller_klass: dotted path to the Unmarshaller class. Defaults tomodernrpc.xmlrpc.backends.marshalling.EtreeElementUnmarshaller.unmarshaller_kwargs: keyword arguments passed to the Unmarshaller. Supported option:allow_none(default:True)
element_type_klass: dotted path to the XML element class used to specialize the generic marshaller/unmarshaller. Defaults tolxml.etree._Element.load_parser_kwargs: keyword arguments passed tolxml.etree.XMLParser. Secure defaults are applied:resolve_entities=False,no_network=True,dtd_validation=False,load_dtd=False,huge_tree=False.load_kwargs: additional arguments forwarded tolxml.etree.fromstring(the constructed parser is injected by the backend).
Example:
Marshaller / Serializer
marshaller_klass: dotted path to the Marshaller class. Defaults tomodernrpc.xmlrpc.backends.marshalling.EtreeElementMarshaller.marshaller_kwargs: keyword arguments passed to the Marshaller. Supported options:allow_none(default:True): whether to allow parsing of<nil/>/Nonevalues.element_factory(default:lxml.etree.Element): the function used to build a new Elementsub_element_factory(default:lxml.etree.SubElement): the function used to build a new SubElement
element_type_klass: dotted path to the XML Element class used to specialize the generic marshaller. Defaults tolxml.etree._Element.dump_kwargs: passed tolxml.etree.tostring.
Example:
xmltodict
Uses third-party xmltodict library. Can be used as both serializer and deserializer.
To use this backend, xmltodict must be installed in the current environment. It can be done with the included
extra dependency xmltodict:
pip install django-modern-rpc[xmltodict]
poetry add django-modern-rpc[xmltodict]
uv add django-modern-rpc[xmltodict]
Pros / Cons
Configuration
Unmarshaller / Deserializer
unmarshaller_klass: dotted path to the Unmarshaller class. Defaults tomodernrpc.xmlrpc.backends.xmltodict.Unmarshaller.unmarshaller_kwargs: keyword arguments passed to the Unmarshaller. Currently, default one doesn’t support any argumentload_kwargs: passed toxmltodict.parse. See the xmltodict docs.
Example:
MODERNRPC_XML_DESERIALIZER = {
"class": "modernrpc.xmlrpc.backends.xmltodict.XmlToDictDeserializer",
"kwargs": {
"load_kwargs": {"disable_entities": False},
}
}
Note: For security reasons, this backend first parses XML with defusedxml.ElementTree before converting it with
xmltodict. Any XML parsing errors or security violations will be reported accordingly.
Marshaller / Serializer
marshaller_klass: dotted path to the Marshaller class. Defaults tomodernrpc.xmlrpc.backends.xmltodict.Marshaller.marshaller_kwargs: keyword arguments passed to the Marshaller. Supported options:allow_none(default:True): whether to allow serialization ofNonevalues.
dump_kwargs: passed toxmltodict.unparse. See the xmltodict docs.
Note: In this backend, the Marshaller/Unmarshaller classes are fixed and cannot be changed via settings.
Example:
JSON-RPC backends
Common Unmarshaller / Marshaller
Unlike XML-RPC backends, JSON-RPC ones are simpler. Basically, a JSON deserializer will convert a string payload into
a structured python data (list, dict, etc.). Then, most of the work will be handled by the Unmarshaller class to build
a valid JsonRpcRequest instance.
On the other hand, the Unmarshaller will convert a JsonRpcResult (success or error) to a valid python dict and
pass the result to the serializer to build the corresponding JSON payload as a string.
Currently, the default JSON-RPC Unmarshaller / Marshaller classes are shared by all backends.
Unmarshaller configuration
Supported kwargs:
validate_version(Default:True): whether to enforce check for"jsonrpc": "2.0"in the incoming request.
Marshaller configuration
Common Marshaller does not support any argument for now.
json (python builtin)
This is the most basic backend that depends on Python’s built-in json module. It is used by default for both
deserialization and serialization of JSON-RPC requests and responses.
By default, this backend use common Unmarshaller and Marshaller classes. In addition, it is configured to use
DjangoJSONEncoder when serializing data, allowing date, time and datetime instances to be serialized
transparently.
Pros / Cons
Configuration
Unmarshaller / Deserializer
unmarshaller_klass: dotted path to the Unmarshaller class. Defaults tomodernrpc.jsonrpc.backends.marshalling.Unmarshaller.unmarshaller_kwargs: see Unmarshaller configurationload_kwargs: passed tojson.loads. See the json.loads() documentation for the list of valid keyword arguments
Marshaller / Serializer
marshaller_klass: dotted path to the Marshaller class. Defaults tomodernrpc.jsonrpc.backends.marshalling.Marshaller.marshaller_kwargs: see Marshaller configurationdump_kwargs: passed tojson.dumps. See the json.dumps() documentation for the list of valid keywords arguments.
Note: By default, json.dumps encoder is overridden to use
DjangoJSONEncoder
through the cls argument, primarily to allow serializing date, time and datetime objects.
simplejson
Uses third party SimpleJSON library. Can be used for both serialization and deserialization.
To use this backend, simplejson must be installed in the current environment. An extra dependency can be used for that:
pip install django-modern-rpc[simplejson]
poetry add django-modern-rpc[simplejson]
uv add django-modern-rpc[simplejson]
Pros / Cons
Configuration
Unmarshaller / Deserializer
unmarshaller_klass: dotted path to the Unmarshaller class. Defaults tomodernrpc.jsonrpc.backends.marshalling.Unmarshaller.unmarshaller_kwargs: see Unmarshaller configurationload_kwargs: passed tosimplejson.loads. See the simplejson.loads() documentation for the list of valid keyword arguments
MODERNRPC_JSON_DESERIALIZER = {
"class": "modernrpc.jsonrpc.backends.simplejson.SimpleJsonDeserializer",
"kwargs": {
"load_kwargs": {"use_decimal": False, "allow_nan": False},
"unmarshaller_klass": "modernrpc.jsonrpc.backends.marshalling.Unmarshaller",
"unmarshaller_kwargs": {"validate_version": False},
}
}
Marshaller / Serializer
marshaller_klass: dotted path to the Marshaller class. Defaults tomodernrpc.jsonrpc.backends.marshalling.Marshaller.marshaller_kwargs: see Marshaller configurationdump_kwargs: passed tosimplejson.dumps. See the simplejson.dumps() documentation for the list of valid keywords arguments.
Note: By default, a custom default function created from Django’s
DjangoJSONEncoder default
method is passed to simplejson.dumps, primarily to allow serializing date, time and datetime objects.
orjson
Uses third party orjson library. Can be used as both serializer and deserializer.
To use this backend, orjson must be installed in the current environment. An extra dependency can be used for that:
pip install django-modern-rpc[orjson]
poetry add django-modern-rpc[orjson]
uv add django-modern-rpc[orjson]
Pros / Cons
Configuration
Unmarshaller / Deserializer
unmarshaller_klass: dotted path to the Unmarshaller class. Defaults tomodernrpc.jsonrpc.backends.marshalling.Unmarshaller.unmarshaller_kwargs: see Unmarshaller configurationload_kwargs: ignored for now.orjson.loadsdoes not accept any additional keyword arguments
Marshaller / Serializer
marshaller_klass: dotted path to the Marshaller class. Defaults tomodernrpc.jsonrpc.backends.marshalling.Marshaller.marshaller_kwargs: see Marshaller configurationdump_kwargs: passed toorjson.dumps. See the orjson.dumps() documentation for the list of valid keywords arguments.
Note: By default, since orjson is already able to serialize date and time objects, no particular encoder
customization is performed by django-modern-rpc.
rapidjson
Uses third party python-rapidjson library. Can be used as both serializer and deserializer.
To use this backend, python-rapidjson must be installed in the current environment. An extra dependency can be used for that:
pip install django-modern-rpc[rapidjson]
poetry add django-modern-rpc[rapidjson]
uv add django-modern-rpc[rapidjson]
Pros / Cons
Configuration
Unmarshaller / Deserializer
unmarshaller_klass: dotted path to the Unmarshaller class. Defaults tomodernrpc.jsonrpc.backends.marshalling.Unmarshaller.unmarshaller_kwargs: see Unmarshaller configurationload_kwargs: passed torapidjson.loads. See the rapidjson.loads() documentation for the list of valid keyword arguments
Marshaller / Serializer
marshaller_klass: dotted path to the Marshaller class. Defaults tomodernrpc.jsonrpc.backends.marshalling.Marshaller.marshaller_kwargs: see Marshaller configurationdump_kwargs: passed torapidjson.dumps. See the rapidjson.dumps() documentation for the list of valid keywords arguments.
Note: By default, date & time handling is set to ISO-8601 via the datetime_mode argument
(rapidjson.DM_ISO8601) to help serializing date, time and datetime objects.
Helper functions
-
modernrpc.helpers.get_builtin_date(date, date_format='%Y-%m-%dT%H:%M:%S', raise_exception=False)[source]
Try to convert a date to a builtin instance of
datetime.datetime. The input date can be astr, adatetime.datetime, axmlrpc.client.Datetimeor axmlrpclib.Datetimeinstance. The returned object is adatetime.datetime.- Parameters:
date (str | datetime | DateTime) – The date object to convert.
date_format (str) – If the given date is a str, it is passed to strptime for parsing
raise_exception (bool) – If set to True, an exception will be raised if the input string cannot be parsed
- Returns:
A valid
datetime.datetimeinstance- Return type:
datetime | None