简体   繁体   中英

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?

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"
      }
    ]
  }
]

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"
      }
    ]
  }
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM