---
myst:
html_meta:
"description": "Writing a serializer or a deserializer"
"property=og:description": "Writing a serializer or a deserializer"
"property=og:title": "Writing a serializer or a deserializer"
"keywords": "Volto, Plone, REST API, plone.restapi, serializer, deserializer"
---
# Writing a serializer or a deserializer
In plone.restapi we have an hierarchy, several levels deep, of serializers and
deserializers adapters. Keep in mind that "serializing" is the operation where
we transform Python objects to a representation (JSON) and deserializing is
when we take that representation (JSON coming from the browser POST, for
example) and convert it to live Python objects. The (de)serializers, with the
type-based lookups are a great example of ZCML use, as they're all implemented
as adapters for the content+request => ISomeSerializationInferface.
1. content based, where the class of the context item is used as discriminator in the adaptor to `plone.restapi.interfaces.ISerializeToJson` (and the counterpart `IDeserializeToJson`.
See the [DX Content serializer][1].
2. field based, used when processing DX Content, where each field/property is adapted for endpoint serialization with the `IFieldSerializer` / `IFieldDeserializer`.
See the [DX Field serializers][2].
3. block based, where we take the JSON data bits that represent a Volto block data and transform it (see the {doc}`writing-block-transforms` chapter).
4. value based, where each Python basic data value needs to be transformed into a JSON-compatible representation, with the `IJsonCompatible` adaptor (use `json_compatible()` helper for this.
See the [converters.py module][3] with these basic serializers.
Here's how the Folder serializer looks like:
```python
@implementer(ISerializeToJson)
@adapter(IDexterityContainer, Interface)
class SerializeFolderToJson(SerializeToJson):
def _build_query(self):
path = "/".join(self.context.getPhysicalPath())
query = {
"path": {"depth": 1, "query": path},
"sort_on": "getObjPositionInParent",
}
return query
def __call__(self, version=None, include_items=True):
folder_metadata = super().__call__(version=version)
folder_metadata.update({"is_folderish": True})
result = folder_metadata
include_items = self.request.form.get("include_items", include_items)
include_items = boolean_value(include_items)
if include_items:
query = self._build_query()
catalog = getToolByName(self.context, "portal_catalog")
brains = catalog(query)
batch = HypermediaBatch(self.request, brains)
result["items_total"] = batch.items_total
if batch.links:
result["batching"] = batch.links
if "fullobjects" in list(self.request.form):
result["items"] = getMultiAdapter(
(brains, self.request), ISerializeToJson
)(fullobjects=True)["items"]
else:
result["items"] = [
getMultiAdapter((brain, self.request), ISerializeToJsonSummary)()
for brain in batch
]
return result
```
[1]: https://github.com/plone/plone.restapi/blob/f5758140d49abdb602cbd3198626fd66871e9b1a/src/plone/restapi/serializer/dxcontent.py
[2]: https://github.com/plone/plone.restapi/blob/f5758140d49abdb602cbd3198626fd66871e9b1a/src/plone/restapi/serializer/dxfields.py
[3]: https://github.com/plone/plone.restapi/blob/f5758140d49abdb602cbd3198626fd66871e9b1a/src/plone/restapi/serializer/converters.py