plone / plone.restapi

RESTful API for Plone.
http://plonerestapi.readthedocs.org/
86 stars 78 forks source link

Support registering serializers / deserializers for Dexterity Schemas #1832

Open ericof opened 1 week ago

ericof commented 1 week ago

Problems to be solved

Example implementation

New Serializer Interface

Register serializers against a new interface

class ISchemaSerializer(Interface):
    """The field serializer multi adapter serializes the field value into
    JSON compatible python data.
    """

    def __init__(schema, context, request):
        """Adapts schema, context and request."""

    def __call__():
        """Returns JSON compatible python data."""

Register new serializers against this interface

@implementer(ISchemaSerializer)
@adapter(IInterface, IDexterityContent, Interface)
class SerializeSchemaToJson:
    """Serialize a schema to JSON."""

Function to serialize all schemata

def serialize_schemas(context: DexterityContent, request: HTTPRequest) -> dict:
    result = {}
    for schema in iterSchemata(context):
        serializer = queryMultiAdapter((schema, context, request), ISchemaSerializer)
        result.update(serializer())
    return result

Refactor dxcontent.py and site.py to use new helper function

        # Insert field values
        result.update(serialize_schemas(obj, self.request))
davisagli commented 1 week ago

@ericof Could you explain the use case please?

davisagli commented 1 week ago

@ericof I'm not convinced yet.

Remove code duplication for schema serialization (dxcontent.py and site.py)

I'm not that worried about the duplication, because we should be able to remove it once we drop support for Plone 5

Allow custom serialization of specific behaviors. A use case would be to serialize a behavior in a different way if the user does not have a specific permission, i.e. masking the data if the user is not allowed to edit the content.

This is already supported by configuring a read_permission for the field, isn't it?

I also don't want to add a new extension mechanism for serialization without also thinking about how it interacts with deserialization. In general when editing the serialized content goes in the redux store in Volto, gets updated, then sent back to the server. So if it's serialized in some unusual format, there needs to be a way to handle it during deserialization as well.

ericof commented 1 week ago

Remove code duplication for schema serialization (dxcontent.py and site.py)

I'm not that worried about the duplication, because we should be able to remove it once we drop support for Plone 5

Good point.

Allow custom serialization of specific behaviors. A use case would be to serialize a behavior in a different way if the user does not have a specific permission, i.e. masking the data if the user is not allowed to edit the content.

This is already supported by configuring a read_permission for the field, isn't it?

No, read_permission is all or nothing, if you don't have it, it won't be serialized. What I need is something "gray". Imagine you have a behavior with a SSN field. If you are able to edit that field, you see the value, otherwise you will see a masked version of this number. (Useful for egov sites where you want to expose data, but to a certain level.)

Also, if I want to add additional information to a behavior serialization, but I don't want to touch the Field serializer, this is useful. In a conference site, I have a behavior with session information that is used my multiple content types. I want to "enrich" the serialization of this behavior by always adding a new key with schema.org metadata to be used. This is meant to be read-only, but added to the serialization of types that use this behavior.

A third use case , that ties to your point bellow, is to write serializers (and deserializers) to group information under a key. For instance, I want all data for my behavior (contact.address) to be grouped under the same key. And then, during the deserialization be exposed again as their own attributes.

I also don't want to add a new extension mechanism for serialization without also thinking about how it interacts with deserialization. In general when editing the serialized content goes in the redux store in Volto, gets updated, then sent back to the server. So if it's serialized in some unusual format, there needs to be a way to handle it during deserialization as well.

Already implementing this support.