Search code examples
dataweavemulesoftmule4

How to split array of object into array of array based on object value using dataweave


In my case, I have one array of object that needs to be split based on "L1" occurrence. For example, the below JSON request has multiple L1.

[
  {
    "route": "F1",
    "Company Code": "One Total Item Count"
  },
  {
    "route": "D1",
    "Company Code": "Two Total PO Amount"
  },
  {
    "route": "L1",
    "Company Code": "Three Total Item Count"
  },
  {
    "route": "F1",
    "Company Code": "One Total PO Amount"
  },
  {
    "route": "D1",
    "Company Code": "Two Total Item Count"
  },
  {
    "route": "L1",
    "Company Code": "Three Total Item Count"
  },
  {
    "route": "D1",
    "Company Code": "Two Total Item Count"
  },
  {
    "route": "L1",
    "Company Code": "Three Total Item Count"
  }
]

I'm trying to split based on L1, and expecting the response like below.

[
  [
    {
      "route": "F1",
      "Company Code": "One Total Item Count"
    },
    {
      "route": "D1",
      "Company Code": "Two Total PO Amount"
    },
    {
      "route": "L1",
      "Company Code": "Three Total Item Count"
    }
  ],
  [
    {
      "route": "F1",
      "Company Code": "One Total PO Amount"
    },
    {
      "route": "D1",
      "Company Code": "Two Total Item Count"
    },
    {
      "route": "L1",
      "Company Code": "Three Total Item Count"
    }
  ],
  [
    {
      "route": "D1",
      "Company Code": "Two Total Item Count"
    },
    {
      "route": "L1",
      "Company Code": "Three Total Item Count"
    }
  ]
]

In dataweave I tried spiltAt, filter, and other functions to split by separate sets based on L1 occurrence. but its not working the way I'm expecting.

Expert, please help me solve this logic.

Thanks in advance.


Solution

  • This can be resolved using a recursive function to split at the first time "L1" appears (splitAt((a indexWhere (item) -> item.route == value) + 1)) then recursively apply the same logic to the rest of the array. We need to be careful of the conditions to finish the recursion to avoid infinite recursion or getting empty arrays.

    The question doesn't clarify if the last element has the "L1" value always. This script should also work if not.

    For a bit extra re usability I made the condition to be a closure. Since my function has two arguments it can be used with in-fix notation in DataWeave, like splitAt().

    %dw 2.0
    output application/json
    import * from dw::core::Arrays
    
    fun splitAfter(a, condition)= do {
        var splitted = a splitAt((a indexWhere condition($)) + 1) 
        ---
        if (sizeOf(a) > 1 and !isEmpty(splitted.l))
            [splitted.l] ++ splitAfter(splitted.r, condition)
        else
            a
    }
    ---
    payload splitAfter (item) -> item.route == "L1"