muledataweavemule4mule-esb

Mule 4 dataweave 2 - how to sort a json object containing other objects


I need to sort a json object ( not an array ) which is not a simple key value Rather it has additional objects inside it

{
"Memo": {
    "itemAmount1": "5",
    "taxName1": "TAX",
    "productPrice1": "10",
    "accountName1": "Account Receivable (Debtors)"
},
"Footer": {
    "productDescription2": "Maggie",
    "itemQuantity2": "49.5",
    "accountName2": "Account Receivable (Debtors)",
    "taxName2": "TAX"
},
"Header": {
    "itemDiscount3": "10",
    "accountName3": "Account Receivable (Debtors)",
    "productPrice3": "10",
    "taxName3": "TAX"
}
}

Expected output is : ( should sort keys of internal objects as well )

 {
"Footer": {
    "accountName2": "Account Receivable (Debtors)",
    "itemQuantity2": "49.5",
    "productDescription2": "Maggie",
    "taxName2": "TAX"
},
"Header": {
    "accountName3": "Account Receivable (Debtors)",
    "itemDiscount3": "10",
    "productPrice3": "10",
    "taxName3": "TAX"
},
"Memo": {
    "accountName1": "Account Receivable (Debtors)",
    "itemAmount1": "5",
    "productPrice1": "10",
    "taxName1": "TAX"
}
}

It is not necessary that it is 2 level object hierarchy it may contain n level of object hierarchy which need to be sorted.

This question is a virtual copy paste of question asked here ( but thats for javascript not dataweave / mule )


Solution

  • The builtin function orderBy() can sort objects too. But to sort children objects you'll need a recursive function that applies orderBy() to the children matching by type.

    %dw 2.0
    output application/json
    fun sortObjects(x)=
        x match {
            case o is Object -> o 
                                  orderBy ((value, key) -> key)
                                  mapObject (($$): sortObjects($))
            else -> $
      }
    ---
    sortObjects(payload)
    

    Output:

    {
      "Footer": {
        "accountName2": "Account Receivable (Debtors)",
        "itemQuantity2": "49.5",
        "productDescription2": "Maggie",
        "taxName2": "TAX"
      },
      "Header": {
        "accountName3": "Account Receivable (Debtors)",
        "itemDiscount3": "10",
        "productPrice3": "10",
        "taxName3": "TAX"
      },
      "Memo": {
        "accountName1": "Account Receivable (Debtors)",
        "itemAmount1": "5",
        "productPrice1": "10",
        "taxName1": "TAX"
      }
    }
    

    Note that adding a match to Array you could use the function to also sort arrays at the same time.