esmero / strawberryfield

A Field of strawberries
GNU Lesser General Public License v3.0
10 stars 5 forks source link

Create a Pass through Serializer/Normalizer #11

Closed DiegoPino closed 1 month ago

DiegoPino commented 5 years ago

Use Case

When outputting via REST view a strawberry field JSON raw content or when using a Metadata Display based on Twig for the same type of field, Drupal double encodes and normalizes the content. This is Ok if the expected output is the whole, double encoded value (for sharing?) but limits us in building new and exciting apps, like OAI-PHM, or even a simple IIIF manifest using views.

Problem

Drupal serializers are only used to simple text values or type data item lists, but strawberry field, even when it can expose through its multiple properties that type of data has also a single ->value element containing an already in JSON format value. To be true to D8 serialization workflow, we need to add a new one that allows a passthrough and some mangling for our already in JSON value. We also need a way of totally passing through serialization if we want to allow field formatters to do that for us, which gives us a huge flexibility, like building full nested responses in any shape we want instead of depending on D8's perception of what data should look like.

Solution

1.- Handle strawberry fields normalizing as a new service attached to our class. See https://www.drupal.org/docs/8/api/serialization-api/changing-the-way-serializer-handles-entities 2.- Allow a JSON passthrough serializer/normalizer and probably a new views display plugin extending RestExport able to deliver our rendered (via formatter) field with any interference. The idea here is to allow our field formatters to decide on the desired format, exposed HTTP header for Content type

By doing so we can truly extend D8's data exposing capabilities without coding.

DiegoPino commented 5 years ago

See (all pretty basic)

https://www.mediacurrent.com/blog/using-normalizers-alter-rest-json-structure-drupal-8/ https://www.adcisolutions.com/knowledge/how-send-json-data-drupal-8-site

Tests Notes:

I will have to run something like

$serializer = \Drupal::service('serializer');
$node = Node::load(2);
$data = $serializer->serialize($node, 'json_passthrough', ['plugin_id' => 'entity']);

To make sure all is working once this is done?

marlo-longley commented 4 years ago

@DiegoPino I read and understood your work in #15, and what the difference in returned format is when StrawberryfieldFieldItemNormalizer is enabled vs disabled, and how it works together with StrawberryFieldItem.

My understanding of the task is to take an input in the format you can see at /do/<id>?_format=json nicely generated by your custom normalizer, and basically reverse the process. What is the larger context of when that reversal would need to take place? Purely over the REST? Understanding that would help me understand the concrete task.

marlo-longley commented 4 years ago

Ok, to clarify the answer that @DiegoPino gave to my above question in conversation. Yes, the task is to reverse. To be able to take an expanded Strawberryfield item and ingest it, through denormalizing in the StrawberryfieldFieldItemNormalizer, into the format the system expects to work with, aka a string. We discussed what the test for success for this task would be: 1) to correctly push an expanded SBF over REST or JSON:API and store it correctly 2) to correctly push JSON files stored in our minio dostorage. Each of these files are full backups of a digital object node, which can bear strawberryfields. The idea would be, in the future, to be able to fully restore Archipelago content based on these files alone.

Regarding test 2, which I took pretty literally. There are certain fields, like the node ID, stored in our minio JSON that cannot be present when creating a new node (uuid is OK). Also, some fields like those containing revision information are immutable (or, at least I was encountering permission issues with them, when operating as admin). These are node level fields, not inside Strawberryfield, so not denormalized with StrawberryfieldFieldItemNormalizer. I started trying to write a node-level Normalizer to deal with them, and asked Diego about the approach.

He pointed out this could potentially be way too powerful and impact the entire system, and suggested we could store potentially store data differently in minio. I agree, messing with Node denormalization is probably bad. Can return to this point later.

(whatever approach we come up with for fields like revision, it will be important to preserve that history, and potentially add a new revision while ingesting, or mark the ingest in some way in the data).

DiegoPino commented 4 years ago

@marlo-longley good explanation. We/you can share a Dumped full Object in JSON here and mark those fields that can not be used via REST. Of course, when thinking about REST v/s a full blown recover-from-filesystem app, on the later, we can always preprocess the dumped JSON, stripping the protected properties out before denormalizing and ingesting skipping the REST endpoint.Not saying REST or JSON API are not needed, indeed we want that to work.

I also feel the all numeric uid and nid and fid (any content entity primary id really) should be removed and/or replaced by their UUID counterparts in our file/json/minio/dumps. Since we will have/already have nodes depending on other nodes or referencing files, and as you know, we have no control on what numeric IDs Drupal will end assigning them, making the interrelation between entities a nightmare to handle when dumping, e.g a full collection and restoring. But UUIDs are stable and can be set!

DiegoPino commented 1 month ago

Implemented