Discussion regarding the complex response structure for REST & GraphQL (Developer Experience)

Hi, it’s been a long time. Does any one have any idea why this code does ABSOLUTLEY NOTHING in React Native? But works perfectly good in React js?

Hmm, maybe it has something to do with Object.prototype.toString.call. I’m no React Native expert, but I can think this isn’t supported natively (pun intended) on React Native.

However, apart from my snippet, i’d suggest you’d use the Transformer | Strapi Market plugin, but that does only work for REST however.

I am following this discussion, read all post up to here.
And I started to get worried about my plan to use Strapi for my project.
I started to explore Strapi with v3 and went to v4 meanwhile and my first experiments did not make me realize yet what these additional structures data/attributes will mean to me in the longer term.
Now I am working on connecting my Vue Storefront frontend with Strapi and I had to learn how GraphQL works and ran into a few unclarities and while resolving them I found this thread.
And I am becoming unhappy with that new format, too.

Thinking about it I realize that there are actually different use cases for Strapi that users (developers) might have and the Strapi team focussees on one direction of use cases that will not be relevant for all developers.
At this time I am one of these who do not care about the feature set behind the new structure. I want simplicity behind the integration I am doing.
So I introduced that branch of the graphql plugin mentioned above that would simplify the format.

I would propose to Strapi to give the users / developers options and enable the simple path as well.
I think that will be fundamental for the product, unless the path that the Strapi team sees is clearly the essential and only one and it is worth to exclude the other use group - that’s whats going to happen that developers looking for simplicity will shy away in the long term.


We are almost finishing this year, so, what a hype!

Hello guys, just came across this thread. Wondering if there is a way to target specific fields data without having it nested in data and attributes i.e. if I want the access the value of a specific field below in the example called snipcartCrawl which in this case is a JSON field, I’d like to be able to access the JSON value of snipcartCrawl (which is currently null) and just have that returned as the API response so my response is just whatever the JSON value is of that field. Is this possible? Managed to wittle it down using ?fields[0]=snipcartCrawl. I only ask because my specific use-case here needs the JSON from the URL rather than retrieving it first and then doing loops etc to access the data within.


I see three possible ways to solve this.

Create a custom route for that use case, attach a custom controller to it, which calls the core controller, but transforms the response to your needs.

Create a custom route which uses the default controller, but attach a custom middleware to it to transform the response to your needs after the default controller has returned the response.

Use Transformer | Strapi Market which reduces the depth of the returned object. You’d still have an object in the response, but it’s not as deeply nested.

In the future our plan is to have our SDK do this (among other additional improvements)

Must it be an SDK? Isn’t it too attached to Strapi?

After reading this topic my team decided stop using strapi and move to our own solution. It’s impossible to keep maintaining structure, update controllers always. Strapi v4 complete fail as product version, I can’t see future in this project

1 Like

I invested a lot of time into strapi 3 - and dealt with the changes in strapi 4 with some client side transforms (a very poor solution I know) - but I think this will be the conclusion of most people looking at the data responses coming back from the server. Really hope it is acknowledged more and dealt with correctly. Strapi is a was a nice project but without addressing this issue I don’t see much of a future either. Unfortunately for me (and many I suspect) moving off will be painful, but necessary without changes. I wouldn’t have used strapi if I looked at Strapi 4 first as well.

We are now more that 1 year after that issue was open and, after a lot of “blabla”, the GraphQL schema is still the same nightmare. In addition, there is no plan to solve this in the futur (excluding v5, because no ETA nor clear commitment).

I have the following feedback:

  • a frontend SDK is NOT a solution in anyway, it just look like putting a band-aid on a wooden leg (what about CURL usage for ex. ?)
  • adding an option (disabled by default) in official GraphQL plugin, something like “use standardized Apollo schema” is NOT a breaking change so the “semver” arg is just irrelevant
  • the reason why this horrible schema was initially introduced is about adding new features in it but… one year later, where are that famous new features??

The logical conclusion is:

  • there is no real, strong reason to keep that schema
  • nothing will happens from Strapi side regarding that issue

So, if you are looking to build a new project with strapi and plan to use it’s API, just run away!
For existing project, you will have to schedule a backend migration in your roadmap.


Since this is a first found google result on “Strapi 4 simplify object”, let me share a simple GTD function which I use:

const simplifyStrapiObject = obj => {
  if (obj.data && obj.data.attributes !== undefined) {
    Object.assign(obj, obj.data.attributes);
    obj.id = obj.data.id;
    delete obj.data;
    delete obj.meta;
  if (obj.attributes) {
    Object.assign(obj, obj.attributes);
    delete obj.attributes;

  const relationships = Object.keys(obj).filter(key => key !== 'data');
  relationships.forEach(relationship => {
    const children = obj[relationship];
    if (Array.isArray(children?.data) && children.data?.length > 0) {
      const mapped = children.data.map(child => simplifyStrapiObject(child))
      obj[relationship] = mapped;
    } else if (children?.data !== undefined) {
      obj[relationship] = simplifyStrapiObject(children)
  return obj;

Use like for any controller, such as super.create() - here for a entity called Payment:

const payment = await super.create(ctx);
return payment;

Please note that this function deliberately removes meta and therefore pagination info. Our use is for quickly returning just-created data.

1 Like

Just started using stapi and started loving it and then suddenly hit boom… very sad to see it, but its nightmare to go with such graphql where meta is more important then data…

any good alternatives to strapi with solid graphql support and nice UI like strapi?

1 Like

I didn’t find any better alternative, and I look around for two or three months.

So, I move to REST with populate parameter.

I wish the docs where more transparent about the issues with GraphQl, then I could have just avoided it and used the rest api.

I am confused, I understood this was not possible and then I see this on the Strapi Blog (Deep Dive into Strapi GraphQL):

I don’t manage to reproduce this very nice behavior.

This blog post is from Strapi v3, when the response structure was much nicer to work with.

1 Like

I just published very simple library which I use for my needs that can be used to flatten graphql responses from strapi v4. What I believe is neat, the typings in the library along with the flattener allow to transform nested typings to a proper flattened types.

1 Like

Hi, can anyone recommend an approach how we solve the Apollo cache issues?
I am not looking to add a ‘flattener’ library to our projects, nor am I interested in extensive explanations about why the current implementation is the way it is.
What I’m after are practical suggestions or strategies that I can use to resolve these Apollo cache problems.

Hi, I made a script to use in the frontend that parses the GraphQL complex response into a simple one while keeping the right typescript types.

Find it here: Flatten Strapi 4's response JSON · GitHub