dataweavemulesoftmule4

MuleSoft - Dataweave 2.0 - Split payload into seperate arrays based on type


Having some trouble splitting a payload up. I basically need to split the payload every time we come across the {"type": "AA"} object.

This is my input payload -

[
    {
        "type": "AA",
        "content": "someContent"
    },
    {
        "type": "AB",
        "content": "someContent"
    },
    {
        "type": "AC",
        "content": "someContent"
    },
    {
        "type": "MH",
        "content": "someContent"
    },
    {
        "type": "AA",
        "content": "someContent"
    },
    {
        "type": "AB",
        "content": "someContent"
    },
    {   
        "type": "AC",
        "content": "someContent"
    },
    {
        "type": "QP",
        "content": "someContent"
    }
]

And what I need to happen is every time we come across the {"type": "AA"} we need to create an array and include all proceeding objects in that array. So this is what the output would look like

[
    [{
        "type": "AA",
        "content": "someContent"
    },
    {
        "type": "AB",
        "content": "someContent"
    },
    {
        "type": "AC",
        "content": "someContent"
    },
    {
        "type": "MH",
        "content": "someContent"
    }],
    [{
        "type": "AA",
        "content": "someContent"
    },
    {
        "type": "AB",
        "content": "someContent"
    },
    {   
        "type": "AC",
        "content": "someContent"
    },
    {
        "type": "QP",
        "content": "someContent"
    }]
]

You can see from the output we have multiple arrays with the first element being the object {"type": "AA"}.. Any help in achieving this output would be greatly appreciated


Solution

  • Assuming that the input always start with type=="AA" we can reuse the clusterWhile() function from this great previous answer: How to Group consecutive dates together which are separated by hour in Dataweave? to group elements of an array while a condition is true.

    %dw 2.0 
    output json
    fun clusterWhile<T>(elements: Array<T>,  criteria: (source:T, target:T) -> Boolean) = do {
        fun clusterLoop(elements, value, carrier, criteria) = 
            elements  match {
                case [] ->  carrier
                case [x ~ xs] ->  
                    if(criteria(value, x)) do {
                        var updatedCarrier = carrier update {
                            case [-1] -> $ << x    
                        }
                        ---
                        clusterLoop(xs, x, updatedCarrier, criteria)
                    }
                else 
                    clusterLoop(xs, x, carrier << [x], criteria)
        }
    
        ---
        elements match {
            case [] -> []
            case [x ~ xs] -> clusterLoop(xs, x, [[x]], criteria)
        }
    }    
    ---
    payload 
        clusterWhile ((source, target) -> !(target."type" == "AA"))
    

    Output:

    [
      [
        {
          "type": "AA",
          "content": "someContent"
        },
        {
          "type": "AB",
          "content": "someContent"
        },
        {
          "type": "AC",
          "content": "someContent"
        },
        {
          "type": "MH",
          "content": "someContent"
        }
      ],
      [
        {
          "type": "AA",
          "content": "someContent"
        },
        {
          "type": "AB",
          "content": "someContent"
        },
        {
          "type": "AC",
          "content": "someContent"
        },
        {
          "type": "QP",
          "content": "someContent"
        }
      ]
    ]