Search code examples
muledataweavemulesoftmule4

Compare two Arrays and return final response based on condition


I have two arrays one is the input payload and the output payload which is coming from target api, now using these two arrays I am trying to frame final response to the end user where I need to match the id in the input payload array to the id field in output payload array and then to display the status for each of them.

input payload

var actualPayload = [
  {
    "id": "b3_12XY335",
    "fName": "test-335",
    "lName": "t335",
    "email": "[email protected]"
  },
  {
    "id": "b3_12XY346",
    "fName": "test-346",
    "lName": "346",
    "email": "[email protected]"
  },
  {
    "id": "b3_12XY347",
    "fName": "test-347",
    "lName": "347",
    "email": "[email protected]"
  },
  {
    "id": "b3_12XY120",
    "fName": "test-120",
    "lName": "120",
    "email": "[email protected]"
  }
]

payload from target system

var payload = {
    "status": "created",
    "error": "error",
    "rows": [{
        "id": "b3_12XY120",
        "status": "created"
    }]
    
}

Now below is my dataweave code

%dw 2.0
import * from dw::core::Strings
output application/json skipNullOn="everywhere"
---
(actualPayload map (item, index) -> {
    (payload.rows map(item1, index1) ->{
        "Id": substringBefore(item.id, "_"),
        "studentId": item.id,
        "status" : if((item.id == item1.id) and (item1.status == "created" or item1.status == "updated") ) true else false,
        
       ("error" : payload.error) if((item1.id != item.id))
    })

        
})

The problem which I am getting with the above dataweave code is when ever the payload.rows array will not come in the case of if all the objects result in to error, then only error information will be returned from target api, but the above dataweave is not returning response in this case.

SO I want the above dataweave code to give me result when the payload.rows is not coming from the target system, then I want to frame the output response with error info coming in the error element for all of the ids in the actual payload.

When there are no rows in the target response, I want the below output to be returned from my dataweave against each of the object in the actual payload with the error mapped from what ever is in the error field in target response and for any rows returned from the target api, I want the above mentioned output coming from the dataweave.

[
  {
    "Id": "b3",
    "studentId": "b3_12XY335",
    "status": false,
    "error": "error"
  },
  {
    "Id": "b3",
    "studentId": "b3_12XY346",
    "status": false,
    "error": "error"
  },
  {
    "Id": "b3",
    "studentId": "b3_12XY347",
    "status": false,
    "error": "error"
  },
  {
    "Id": "b3",
    "studentId": "b3_12XY120",
    "status": false,
    "error": "error"
  }
]

Solution

  • The issue with the provided code is that mapping only happens when there is a rows object. Instead of this, you can do a lookup on the rows with the id. Lookup object can be created by using groupBy to group the rows in the payload by Id. This way, rows are not iterated for each item in the actual payload.

    %dw 2.0
    import * from dw::core::Strings
    output application/json
    var actualPayload = [
      {
        "id": "b3_12XY335",
        "fName": "test-335",
        "lName": "t335",
        "email": "[email protected]"
      },
      {
        "id": "b3_12XY346",
        "fName": "test-346",
        "lName": "346",
        "email": "[email protected]"
      },
      {
        "id": "b3_12XY347",
        "fName": "test-347",
        "lName": "347",
        "email": "[email protected]"
      },
      {
        "id": "b3_12XY120",
        "fName": "test-120",
        "lName": "120",
        "email": "[email protected]"
      }
    ]
    
    var groupedRowsById = payload.rows default [] groupBy $.id
    var statusesToMatch = ["created", "updated"]
    ---
    (actualPayload map (item, index) -> do {
        var matchedRow = groupedRowsById [item.id]
        ---
        {
            Id: substringBefore(item.id, "_"),
            studentId: item.id,
            status: ((! isEmpty(matchedRow)) and (statusesToMatch contains (matchedRow[0].status))),
            (error: payload.error) if (isEmpty(matchedRow))
        }
    })
    

    Output:

    [
      {
        "Id": "b3",
        "studentId": "b3_12XY335",
        "status": false,
        "error": "error"
      },
      {
        "Id": "b3",
        "studentId": "b3_12XY346",
        "status": false,
        "error": "error"
      },
      {
        "Id": "b3",
        "studentId": "b3_12XY347",
        "status": false,
        "error": "error"
      },
      {
        "Id": "b3",
        "studentId": "b3_12XY120",
        "status": true
      }
    ]