netiv
netiv

Reputation: 73

In Dataweave 2.0 how to create nested array from flat array - Mule 4

I need to create a nested array using the response received from different API. I have this flat array, with all the data. What would be the best approach to create a nested array where the children are nested to its parent based on its result status.

Input JSON flat array as follows:

  [
   {
    "studentNumber": "FP5500",
    "studentName": "John Doe",
    "Subject": "Arts",
    "grade": "B",
    "result": "Pass"
   },{
    "studentNumber": "FP5501",
    "studentName": "Jane Doe",
    "Subject": "Arts",
    "grade": "B",
    "result": "Pass"
   },{
    "studentNumber": "FP5501",
    "studentName": "Jane Doe",
    "Subject": "Economics",
    "grade": "A",
    "result": "Pass"
   },{
    "studentNumber": "FP5502",
    "studentName": "Bane Doe",
    "Subject": "Arts",
    "result": "Fail"
   }
]

Expecting output as nested array like below format:

[
  {
   "studentNumber": "FP5500",
   "studentName": "John Doe",
   "Status": "Pass",
   "reportDetails": {
     "Subject": "Arts",
     "grade": "B"
    }
  },
  {
   "studentNumber": "FP5501",
   "studentName": "Jane Doe",
   "Status": "Pass",
   "reportDetails": [{
     "Subject": "Arts",
     "grade": "B"
    },
    {
     "Subject": "Economics",
     "grade": "A"
    }]
  } 
]

Fourth element (3rd student) in array should be ignored as "result" is "Fail", but the first two students should be included in the response, there should be only entry for "StudentName" => Jane Doe with nested array for subject details.

I did my research and couldn't find a valid solution(without using for or foreach loop). I tried map and filter on duplicate map with mapObject but no progress. How do I solve this?

Upvotes: 0

Views: 759

Answers (2)

Manik Magar
Manik Magar

Reputation: 1401

Accepted answer's script output doesn't seem to match with OP's expected output. Not sure why that is accepted answer.

Here is another script -

%dw 2.0
output application/json
---
(payload filter ((student) -> student.result == 'Pass') 
    groupBy ((student) -> student.studentNumber))
        pluck $ 
            reduce (item, accumulator= []) -> 
                accumulator ++ [(item[0] - "grade" - "Subject" - "result") 
                    ++ {Status: item[0].result, resultDetails: item map {Subject: $.Subject, grade: $.grade}}]
        
                

Produces -

[
  {
    "studentNumber": "FP5500",
    "studentName": "John Doe",
    "Status": "Pass",
    "resultDetails": [
      {
        "Subject": "Arts",
        "grade": "B"
      }
    ]
  },
  {
    "studentNumber": "FP5501",
    "studentName": "Jane Doe",
    "Status": "Pass",
    "resultDetails": [
      {
        "Subject": "Arts",
        "grade": "B"
      },
      {
        "Subject": "Economics",
        "grade": "A"
      }
    ]
  }
]

Upvotes: 0

Salim Khan
Salim Khan

Reputation: 4303

A quick and easy way could be as follows:

Script

%dw 2.0
output application/json
---
[payload filter $.result != "Fail" groupBy $.studentNumber   mapObject {
    "studentNumber": $.studentNumber[0],
    "studentName":  $.studentName[0],
    "Subject": $.Subject[0],
    "Status": $.result[0],
    (if (sizeOf($) == 1)
     "reportDetails": ($ map {
        "Subject": $.Subject,
        "Grade": $.grade
    
    })[0]
    else
    "reportDetails": $ map {
        "Subject": $.Subject,
        "Grade": $.grade
    
    })
    
}]

Output

[
  {
    "studentNumber": "FP5500",
    "studentName": "John Doe",
    "Subject": "Arts",
    "Status": "Pass",
    "reportDetails": {
      "Subject": "Arts",
      "Grade": "B"
    },
    "studentNumber": "FP5501",
    "studentName": "Jane Doe",
    "Subject": "Arts",
    "Status": "Pass",
    "reportDetails": [
      {
        "Subject": "Arts",
        "Grade": "B"
      },
      {
        "Subject": "Economics",
        "Grade": "A"
      }
    ]
  }
]

Upvotes: 3

Related Questions