Dear Strapi team,
Why so many ‘data/attributes’ flying around?
I really like Strapi (there are so many more pros than cons) but have been struggling with your recent changes in v4 related to the ‘Unified response format,’ even wondering if there might be an alternate headless solution that might prove to be more effective.
If one is trying to consume a single endpoint that has 2 or 3 levels hierarchy, which easily occurs when one defines any relations, media fields, components, or dynamic zones, it seems likely that the developer (who uses Strapi to build the hierarchy) would be the one responsible for any necessary meta or pagination that runs so deeply within the model they’re constructing, making the data/attribute wrapping redundant for a majority of the use cases beyond the 2nd level.
In your documentation, you say a single entry returns an object with id, attributes, and meta. This seems logical for level 1 ( of which I would be in accord), as I would consider the endpoint to be one query (regardless of filtering parameters); any subsequent level queries are not directly part of the interface.
As an initial test, I have spent some time creating a transformation layer to remove this wrapping (in one instance, trimming by 4 data/attribute levels), but have yet to come up with a standard and clean approach to use across all my models.
In my opinion, I shouldn’t really need to create a transformation layer specifically to eliminate what in all current practices feels like an arbitrary rule for distant future-proofing.
I’ve considered several solutions: 1) restrict my models to a single dynamic zone across one level (which isn’t ideal in all cases for data-entry, and defeats the flexibility of Strapi’s types), thus keeping the response flatter; 2) create a middleware service to transform the response (as others have suggested), but this seems too cumbersome and not the best place to perform such a transformation; 3) create a plugin to handle transformations, which is not ideal but would in theory be helpful for migrations; or 4) find another headless CMS with a cleaner response format.
I would hate to have gone into production with v3 (the version and response structure that originally won me over) and be faced with adding a transformation layer to migrate to v4.
The following would be ideal for dev-friendly front-end consumption:
Apps should be able map the object with ease without transformation:
‘page.content.type’ instead of ‘data.attributes.page.content.type.data.attributes.name.’
For instance, with a Vue component, passing data attributes from the response should map sensibly without the front-end dev having to unnecessarily transform the object to remove verbosity (at least, that is what I wish to provide her/him):
<component v-bind:is="$compName(attrs.__component)" :attributes="attrs" />
instead of;
<component
v-bind:is="$compName(data.attributes.page.content.__component)"
:attributes="data.attributes.page.content.attrs"
/>
I hope you will at least consider removing the data/attributes wrapper (from both REST and GraphQL APIs) on nested objects that do not require meta/pagination, or include them only when directly called by an endpoint return one level. I hope this feedback is helpful.