Search code examples
muledataweavemulesoftmule4

Derive parent-child hierarchy in JSON from an array using DataWeave


Hopefully this is the last of my questions related to this and this

The earlier questions were related to generating XML payload while this query is around generating JSON o/p in a specific format...

Thanks to @Harshank and @sudhish_s was able to make some progress with XML o/p. However I am not able to figure out how to go about json o/p

Here is the input payload ( have limited it to three rows / json objects but could be in thousands)

    [
  {
    "gp": "S1",
    "gp_eye_colour": "blue",
    "gp_name" : "John",
    "parent": "S1",
    "parent_eye_colour" : "blue",
    "parent_name" : "Sam",
    "child": "C1",
    "child_eye_colour" : "black",
    "child_name" : "C1-name"
  },
 {
    "gp": "S1",
    "gp_eye_colour": "blue",
    "gp_name" : "John",
    "parent": "P1",
    "parent_eye_colour" : "blue",
    "parent_name" : "Don",
    "child": "C1",
    "child_eye_colour" : "brown",
    "child_name" : "C1-name"
  } ,
  {
    "gp": "S2",
    "gp_eye_colour": "blue",
    "gp_name" : "David",
    "parent": "P2",
    "parent_eye_colour" : "blue",
    "parent_name" : "Martha",
    "child": "C1",
    "child_eye_colour" : "brown",
    "child_name" : "C1-name"
  }  
]

Desired o/p is as below :

{
    "S2_blue": {
        "code": "S2",
        "eyeColour": "blue",
        "name": "David",
        "hierarchy": [
            {
                "code": "P2",
                "eyeColour": "blue",
                "name": "Martha",
                "hierarchy": [
                    {
                        "code": "C1",
                        "eyeColour": "brown",
                        "name": "C1-name",
                        "hierarchy": []
                    }
                ]
            }
        ]
    },
    "S1_blue": {
        "code": "S1",
        "eyeColour": "blue",
        "name": "John",
        "hierarchy": [
            {
                "code": "P1",
                "eyeColour": "blue",
                "name": "Don",
                "hierarchy": [
                    {
                        "code": "C1",
                        "eyeColour": "brown",
                        "name": "C1-name",
                        "hierarchy": []
                    }
                ]
            },
            {
                "code": "C1",
                "eyeColour": "black",
                "name": "C1-name",
                "hierarchy": []
            }
        ]
    }
}

Similar rules need to apply :

  1. Its a Grandparent >> Parent >> Child hierarchy
  2. If Grandparent and Parent share same characteristics (gp == parent and gp_eye_colour == parent_eye_colour then skip parent and directly include child(ren) ( as an example parent Sam is excluded since John (gp) has the same value for gp and eye_colour
  3. Don is not exluded ( same rule as above )

Using the solutions provided to the earlier asked questions - I came up with the following code:

    %dw 2.0
output application/json
var hierarchy = ["gp", "parent", "child"]
fun getDirectGeanologies(records, level) = do {
    var hLevel = hierarchy[level]
    var xyz =  if(level == 0)
    (records groupBy ((item, index) -> item.gp ++ "_" ++ item.gp_eye_colour) )
    else if(level == 1)
    (records groupBy ((item, index) -> item.parent ++ "_" ++ item.parent_eye_colour))
    else
    (records groupBy ((item, index) -> item.child ++ "_" ++ item.child_eye_colour))
    ---
     xyz mapObject ((children, code) ->      
        (code): {
            code: children[0][hLevel],
            eyeColour: children[0][hLevel ++ "_eye_colour"],
            name: children[0][hLevel ++ "_name"],
            hierarchy:  
                if (level == sizeOf(hierarchy) - 1) [] // if level = 2 ( child stop recursion)
                else do {
                    var nextLevel = level + 1
                    var nextGen = if(nextLevel == 1)(children groupBy ((item, index) -> item.parent ++ "_" ++ item.parent_eye_colour)) else (children groupBy ((item, index) -> item.child ++ "_" ++ item.child_eye_colour))
                    --- 
                    nextGen mapObject ((nextGenChildren, nextGenCode) -> 
                        if (nextGenCode == code)
                            getDirectGeanologies (nextGenChildren, nextLevel + 1 ) // skip parent
                        else
                            getDirectGeanologies (nextGenChildren, nextLevel)
                    )                   
                }
                                                        
        }
    )
}
---
getDirectGeanologies(payload,0)

However it is not producing desired o/p :

    {
  "S1_blue": {
    "code": "S1",
    "eyeColour": "blue",
    "name": "John",
    "hierarchy": {
      "C1_black": {
        "code": "C1",
        "eyeColour": "black",
        "name": "C1-name",
        "hierarchy": [
          
        ]
      },
      "P1_blue": {
        "code": "P1",
        "eyeColour": "blue",
        "name": "Don",
        "hierarchy": {
          "C1_brown": {
            "code": "C1",
            "eyeColour": "brown",
            "name": "C1-name",
            "hierarchy": [
              
            ]
          }
        }
      }
    }
  },
  "S2_blue": {
    "code": "S2",
    "eyeColour": "blue",
    "name": "David",
    "hierarchy": {
      "P2_blue": {
        "code": "P2",
        "eyeColour": "blue",
        "name": "Martha",
        "hierarchy": {
          "C1_brown": {
            "code": "C1",
            "eyeColour": "brown",
            "name": "C1-name",
            "hierarchy": [
              
            ]
          }
        }
      }
    }
  }
}

The issues here are :

  1. hierarchy inside gp should be an array but I am getting a object
  2. Not 100% sure but because of above problem rather than having objects inside an array against hierarchy I am getting an object with key as parent/child and eye colour ( Ex : C1_black , P1_blue etc )

So not really sure how to get this part and I am having a tough time to visualise the recursive behaviour Thanks in advance and once again really appreciate the help already provided by @Harshank and @sudhish_s


Solution

  • I have answered this in mulesoft help forum. LInk MuleSoft Help Forum link