muledataweavemule4

How to create an array based on keys after the filter condition?


I have a array as shown below which is an output of the filter condition. It has fields like documentItemName1,documentItemName2,documentItemName3 at the min it can have on and max of 3.

It's like for each contentVersion documentItemToSigner has no of number objects based on no of documentItemName{n} present in it

payload:

 [
      {
        "contentVersion": "068DQ000000lK0iYAE",
        "documentName": "ESRA with Exhibit_A",
        "documentItemName1": "Signature001",
        "typeCd1": "Signature",
        "typeCd2": null,
        "typeCd3": null,
        "subtypeCd1": "CAPTURE",
        "subtypeCd2": null,
        "subtypeCd3": null
      },
      {
        "contentVersion": "068DQ000000kK0OYAU",
        "documentName": "Agreement 1",
        "documentItemName1": "Signature001",
        "documentItemName2": "Signature002",
        "typeCd1": "Signature",
        "typeCd2": "Signature",
        "typeCd3": null,
        "subtypeCd1": "CAPTURE",
        "subtypeCd2": "LABEL",
        "subtypeCd3": null
      },
      {
        "contentVersion": "068DQ000000lK0OYAU",
        "documentName": "Agreement 2",
        "documentItemName1": "Signature001",
        "documentItemName2": "Signature002",
        "documentItemName3": "Signature003",
        "typeCd1": "Signature",
        "typeCd2": "Signature",
        "typeCd3": "Signature",
        "subtypeCd1": "CAPTURE",
        "subtypeCd2": "CAPTURE",
        "subtypeCd3": "CAPTURE"
      }
    ]

I have tried below script but not sure how to create objects based on no of documentItemName{no} in it.

For ex: From the payload I am filtering to this contentVersion = "068DQ000000lK0OYAU" which has documentItemName1,documentItemName2,documentItemName3. So, documentItemToSigner array should have 3 objects which maps like this

"documentItemToSigner": [{

documentItemName: documentItemName1,
"typeCd": typeCd1,
"subtypeCd": subtypeCd1
},
 {

documentItemName: documentItemName2,
"typeCd": typeCd2,
"subtypeCd": subtypeCd3
},
 {

documentItemName: documentItemName3,
"typeCd": typeCd3,
 "subtypeCd": subtypeCd3
}]

For ex2: From the payload, If I am filtering to this contentVersion = "068DQ000000lK0iYAE" which has only documentItemName1. So, documentItemToSigner array should have 1 object which maps like this

"documentItemToSigner": [{
        
        documentItemName: documentItemName1,
        "typeCd": typeCd1,
        "subtypeCd": subtypeCd1
        }]
    
"documentItemToSigner": (payload filter ((g, index) -> g.contentVersion == "068DQ000000lK0OYAU")) map ((item, index) -> {
    "typeCd": item."typeCd{n}",
    "subtypeCd": item."subtypeCd{n}",
    "eSignLiveExtension": {
      "extractInd": true
    },
    "documentItemName": item."documentItemName{n}"
  })

expected output:

{
  "documentItemToSigner": [
    {
      "typeCd": "Signature",
      "subtypeCd": "CAPTURE",
      "eSignLiveExtension": {
        "extractInd": true
      },
      "documentItemName": "Signature001"
    },
    {
      "typeCd": "Signature",
      "subtypeCd": "LABEL",
      "documentItemName": "Signature002",
      "eSignLiveExtension": {
        "extractInd": false
      }
    },
 {
      "typeCd": "Signature",
      "subtypeCd": "CAPTURE",
      "eSignLiveExtension": {
        "extractInd": true
      },
      "documentItemName": "Signature003"
    }
  ]
}

Solution

  • I extracted the attributes from the payload that end in a number and format it in a way that is easy to map to the desired output.

    This solution assumes a single digit for the suffix. Also extractInd is fixed to true, since there is no guidance on how to make it dynamic like in the example output.

    %dw 2.0
    output application/json
    ---
    {
        "documentItemToSigner": 
            (payload filter ((g) -> g.contentVersion == "068DQ000000lK0OYAU")) 
        
            // convert to a list of attributes per numeric suffix of keys
            map ((item) -> 
                item groupBy (dw::core::Strings::last($$ as String, 1)) filterObject ((value, key) -> dw::core::Strings::isNumeric(key as String )) 
                pluck {index:$$, value: $}
            )
    
            // map the list per suffix attributes to a list of objects
            flatMap ((item, index) -> item map ((doc) ->  {
                "typeCd": doc.value[("typeCd" ++ doc.index)],
                "subtypeCd": doc.value[("subtypeCd" ++ doc.index)],
                "eSignLiveExtension": {
                "extractInd": true
                },
                "documentItemName":  doc.value[("documentItemName" ++ doc.index)]
            }))
    }
    

    Output

    {
      "documentItemToSigner": [
        {
          "typeCd": "Signature",
          "subtypeCd": "CAPTURE",
          "eSignLiveExtension": {
            "extractInd": true
          },
          "documentItemName": "Signature001"
        },
        {
          "typeCd": "Signature",
          "subtypeCd": "CAPTURE",
          "eSignLiveExtension": {
            "extractInd": true
          },
          "documentItemName": "Signature002"
        },
        {
          "typeCd": "Signature",
          "subtypeCd": "CAPTURE",
          "eSignLiveExtension": {
            "extractInd": true
          },
          "documentItemName": "Signature003"
        }
      ]
    }