-3

I have a filter criteria to apply on REST response. This response have nested sub objects. For loop going in task and filter function is not working on nested array objects. Please help me to filter the below JSON array object based on body.items[index].details.items[index].Id value.

So here I am looking to keep only the arrays in body.items.details.items which matches with 300100619883728.

JSON :

{
    "error": null,
    "message": {
      "summary": ""
    },
    "status": 200,
    "headers": {},
    "body": {
      "items": [
        {
          "Name": "Test1",
          "LastName": "ABC",
          "details": {
            "items": [
              {
                "Id": "300100619883728",
                "Status": "Draft",
                "subDetails": {
                  "items": [
                    {
                      "CurrentAddress": "Some address"
                    }
                  ],
                  "totalResults": 1,
                  "count": 1,
                  "hasMore": false,
                  "limit": 25,
                  "offset": 0
                }
              },
              {
                "Id": "300100619883738",
                "Status": "Draft",
                "subDetails": {
                  "items": [
                    {
                      "CurrentAddress": "Some Address"
                    }
                  ],
                  "totalResults": 1,
                  "count": 1,
                  "hasMore": false,
                  "limit": 25,
                  "offset": 0
                }
              }
            ],
            "totalResults": 2,
            "count": 2,
            "hasMore": false,
            "limit": 25,
            "offset": 0
          }
        },
        {
          "Name": "Test2",
          "LastName": "ABC",
          "details": {
            "items": [
              {
                "Id": "300100619883728",
                "Status": "Draft",
                "subDetails": {
                  "items": [
                    {
                      "CurrentAddress": "Some address"
                    }
                  ],
                  "totalResults": 1,
                  "count": 1,
                  "hasMore": false,
                  "limit": 25,
                  "offset": 0
                }
              },
              {
                "Id": "300100619883739",
                "Status": "Draft",
                "subDetails": {
                  "items": [
                    {
                      "CurrentAddress": "Some Address"
                    }
                  ],
                  "totalResults": 1,
                  "count": 1,
                  "hasMore": false,
                  "limit": 25,
                  "offset": 0
                }
              }
            ],
            "totalResults": 2,
            "count": 2,
            "hasMore": false,
            "limit": 25,
            "offset": 0
          }
        }
      ],
      "totalResults": 2
    },
    "ok": true,
    "statusText": "OK"
  }

Expected result after filtering is without change in structure of array is:

{
    "error": null,
    "message": {
      "summary": ""
    },
    "status": 200,
    "headers": {},
    "body": {
      "items": [
        {
          "Name": "Test1",
          "LastName": "ABC",
          "details": {
            "items": [
              {
                "Id": "300100619883728",
                "Status": "Draft",
                "subDetails": {
                  "items": [
                    {
                      "CurrentAddress": "Some address"
                    }
                  ],
                  "totalResults": 1,
                  "count": 1,
                  "hasMore": false,
                  "limit": 25,
                  "offset": 0
                }
              }
            ],
            "totalResults": 2,
            "count": 2,
            "hasMore": false,
            "limit": 25,
            "offset": 0
          }
        },
        {
          "Name": "Test2",
          "LastName": "ABC",
          "details": {
            "items": [
              {
                "Id": "300100619883728",
                "Status": "Draft",
                "subDetails": {
                  "items": [
                    {
                      "CurrentAddress": "Some address"
                    }
                  ],
                  "totalResults": 1,
                  "count": 1,
                  "hasMore": false,
                  "limit": 25,
                  "offset": 0
                }
              }
            ],
            "totalResults": 2,
            "count": 2,
            "hasMore": false,
            "limit": 25,
            "offset": 0
          }
        }
      ],
      "totalResults": 2
    },
    "ok": true,
    "statusText": "OK"
  }

filter I tried to get the desired result but could not go to nested object to access its value and filter.

const filteredObj = obj.body.items.filter(function (item) {
   return item.details.items == 300100619883728;
});
2
  • res.body.items.forEach(e => { e.details.items = e.details.items.filter(i => i.Id==='300100619883728')
    – cmgchess
    Commented Jul 7 at 13:24
  • Thank you everyone for the help. I am new to JS so my question was not properly arranged. Thanks for the understanding. Commented Jul 7 at 14:34

1 Answer 1

2

What you intend to do is not as simple as it looks: You don't want to filter a single array, but multiple arrays (details.items) that are each inside objects that are members of a higher array (body.items).

If you don't mind mutating the original response (which usually isn't good practice), the below line of code would do the trick.

response.body.items.forEach(item => item.details.items = item.details.items.filter(item => item.Id === ID_TO_FIND));

What we say here is the following: For each item in body.items, filter that item's details.items to keep only the ones with the desired Id.

However, the cleaner solution is to create a new copy of the response, with a new body.items where each item's details.items is filtered. Here is how that works:

const ID_TO_FIND = "300100619883728"; // The id we want to keep

// The map() function creates a new copy of an array,
// while allowing us to change how each element in that copy looks like
const fileterdBodyItems = response.body.items.map(item => { 

  // For each item in the body, we create a filtered copy of that item's details
  const fileterdDetailsItems = item.details.items.filter(item => item.Id === ID_TO_FIND)

  // Now, we create a new details object for that item, which uses all the original
  // attributes of the original details, except for items; we replace them with 
  // fileterdDetailsItems 
  const fileterdDetails = { ...item.details, items: fileterdDetailsItems };

  // Like the above, we want the filtered item to contain all the original
  // attributes of the original item, except for details, replacing them with
  // filtered details
  const filteredItem = { ...item, details: fileterdDetails };

  // Each object returned from the map() function's callback will become one
  // element in fileterdBodyItems
  return filteredItem ;
});

// This should be familiar by now
const fileterdBody = {...response.body, items: fileterdBodyItems};
const filteredResponse = {...response, body: fileterdBody}
1
  • Hi @Kinan Dira. Thanks a lot for this help. The solution worked perfectly.! Commented Jul 7 at 14:33

Not the answer you're looking for? Browse other questions tagged or ask your own question.