Best approach to Post nested objects

System Information
  • Strapi Version: 3.6.2
  • Operating System: macOS Catalina 10.15.7
  • Database: PostgresSQL 13
  • Node Version: 14.15.5
  • NPM Version: 6.14.11
  • Yarn Version: 1.22.10

Hello,

I am trying to add rows to a table via nested post. my set up is as follows:

Collection type:
Session

  • session_id
  • timestamp
  • relation (Session has many Answers)

Answers

  • value1 (text)
  • value2 (text)

I want to create one session with multiple answer objects.
When I make a Post request, it fails as answer objects are not inserted into the table correctly. the body of the post :

{
    "session_id": "12345678901",
    "timestamp": "2021-05-20T11:04:34.417Z",
    "answers": 
    [
        {  
            "value1": "a",
            "value2": "b"
        },
        {  
            "value1": "c",
            "value2": "d"
        }
    ]
} 

I can see session_id, timestamp values appear for Session.
I can also see the id’s appearing in the reference table that is auto generated,
but the nested objects that should create values in Answers objects is not added to the answers table.

The get request returns the following, with an empty list where answers objects should return:

{
    "id": 8,
    "session_id": "12345678901",
    "timestamp": "2021-05-20T11:04:34.417Z",
    "published_at": "2021-05-20T13:16:48.071Z",
    "created_at": "2021-05-20T13:16:48.079Z",
    "updated_at": "2021-05-20T13:16:48.079Z",
    "answers": []
}

Using postman to test.

Found the solution based on this topic..

Default logic is create the inner objects, then attach a reference to those inner objects (their unique id’s) in the outer/parent object POST.
However, this means that you would need to make x number of inner object POSTS, get their id’s, temporary store and include them in another outer/parent object POST. So if you had 10 inner objects, you would end up making 10 POST requests + 1 for outer/parent object POST.

I wanted to do this as it was more elegant and you don’t burden the front-end with dictating the request structure. This method exposes only 1 POST request at outer/parent object level and returns the output correctly as 1 object. BUT technically, it still makes 10 inner object POST’s in the backend.

Continuing on with the example in the link above:

'use strict';
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');

// /**
//  * Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-controllers)
//  * to customize this controller
//  */

module.exports = {
  /**
   * Create a record.
   *
   * @return {Object}
   */

  async create(ctx) {
    let newArticle = ctx.request.body
    let entity;
    let newTags = [];

    // Loop through inner tags if they exist.
    if (newArticle.tags.length > 0) {
      for (let i = 0; i < newArticle.tags.length; i++) {
            // 'tag' refers to model file name, in this case tag.js
           // by default, strapi takes the entire object, unless specified ( name: newArticle.tags[I].tag_name)
            let newTag = await strapi.query('tag').create(newArticle.tags[i]) 
            newTags.push(newTag.id) // use these id's in parent POST
      }
      
      newArticle.tags = newTags // now it has id's from inner objects to push into parent object and reference table in db. 
    }

    if (ctx.is('multipart')) {
      // need to adjust this for the tags, right now it will break
      const { data, files } = parseMultipartData(ctx);
      entity = await strapi.services.article.create(data, { files });
    } else {
      // pass the new request body with the proper array of IDs and create the article
      entity = await strapi.services.article.create(newArticle);
    }
    return sanitizeEntity(entity, { model: strapi.models.article });
  },
};

Since this is a google result for “Strapi created nested object”, is there any REST friendly approch in Strapi v4 as of June, 2023?

I will create a middleware that will do this shit automatically

1 Like

:joy: yeah everyone’s gotta grind and write their own

Not anymore my dude