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.
content based, where the class of the context item is used as discriminator in the adaptor to
plone.restapi.interfaces.ISerializeToJson(and the counterpartIDeserializeToJson. See the DX Content serializer.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.block based, where we take the JSON data bits that represent a Volto block data and transform it (see the Writing a block transform chapter).
value based, where each Python basic data value needs to be transformed into a JSON-compatible representation, with the
IJsonCompatibleadaptor (usejson_compatible()helper for this. See the converters.py module with these basic serializers.
Here's how the Folder serializer looks like:
@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