Search code examples
filtersub-arrayjsonata

How can the sub-array of an array be filtered in JSONata


In the following array how can the object with "step":"2" be removed from the sub-array "subGroupB" only when "code":"code-333"?

{
  "mainGroup":[
    {
      "subGroupA":{
         "id": "id-111",
         "code": "code-111"
      },
      "subGroupB": [
         {
         "step": "1",
         "code": "code-111"
         },
         {
         "step": "2",
         "code": "code-111"
         }    
       ]
    },
    {
      "subGroupA":{
         "id": "id-222",
         "code": "code-222"
      },
      "subGroupB": [
         {
         "step": "1",
         "code": "code-222"
         },
         {
         "step": "2",
         "code": "code-222"
         }   
       ]
    },
    {
      "subGroupA":{
         "id": "id-333",
         "code": "code-333"
      },
      "subGroupB": [
         {
         "step": "1",
         "code": "code-333"
         },
         {
         "step": "2",
         "code": "code-333"
         }}           
       ]
    }
  ]
}

The expected result is:

{
  "mainGroup":[
    {
      "subGroupA":{
         "id": "id-111",
         "code": "code-111"
      },
      "subGroupB": [
         {
         "step": "1",
         "code": "code-111"
         },
         {
         "step": "2",
         "code": "code-111"
         }    
       ]
    },
    {
      "subGroupA":{
         "id": "id-222",
         "code": "code-222"
      },
      "subGroupB": [
         {
         "step": "1",
         "code": "code-222"
         },
         {
         "step": "2",
         "code": "code-222"
         }   
       ]
    },
    {
      "subGroupA":{
         "id": "id-333",
         "code": "code-333"
      },
      "subGroupB": [
         {
         "step": "1",
         "code": "code-333"
         }           
       ]
    }
  ]
}

I have tried to $filter the last object's sub-array and $append it to the first two objects using variables, but the last object gets broken into two objects and I end up with 4 objects instead of three.


Solution

  • You can do it by filtering the subGroupB inside a mapped mainGroup like this:

    {
      "mainGroup": mainGroup.{
        "subGroupA": subGroupA,
        "subGroupB": subGroupB[$not(code="code-333" and step="2")][]
      }[]
    }
    

    See it on the playground: https://stedi.link/QOLs3Mf

    Alternatively, you can use the transform operator, if you don't want to reconstruct the whole object structure yourself:

    $$ ~> |mainGroup|{ "subGroupB": subGroupB[$not(code="code-333" and step="2")][] }|
    

    Also, on the playground: https://stedi.link/q5jEof2