1

I am trying to achieve the below output from the given input. I have tried several ways of making a generic function so that when any data is passed with similar structure I get the similar output. Please help me to achieve this.

Input

[{
  "name": "Thinker",
  "details": [
      {
      "num": 1
      }, 
      {
      "num": 2
      }
   ]
}, 
{
  "name": "Blinker",
  "details": [
      {
      "num": 3
      }, 
      {
      "num": 4
      }
   ]
}]

Output

[{
  "name": "Thinker",
  "num": 1
},
{
  "name": "Thinker",
  "num": 2
},
{
  "name": "Blinker",
  "num": 3
},
{
  "name": "Blinker",
  "num": 4
}]
Thinker-101
  • 554
  • 5
  • 19
  • 1
    You should share what you already tried to avoid people doing rework. Kindly read https://stackoverflow.com/help/how-to-ask for tips on how to improve your question. Also please clarify what do you understand for generic in the context of your question. – aled Mar 04 '22 at 15:36

4 Answers4

4

The key is mapping through both outer and inner arrays and then flattening the result:

output application/json
---
flatten (payload map ((item, index) -> item.details map ((detail, index) -> {
    name: item.name,
    num: detail.num
})))
afelisatti
  • 2,770
  • 1
  • 13
  • 21
  • 2
    The usage of flatten() could be replaced by changing the first map() to flatMap(). – aled Mar 04 '22 at 15:35
3

As Aled has mentioned in his comments to one of the answers, this could be another way to solve this.

%dw 2.0
output application/json
---
payload flatMap (item,index) -> (
      item.details map {
           name: item.name,
           num:  $.num
      }
)
Salim Khan
  • 4,233
  • 11
  • 15
2

Try this DW

1st Map to Map on main array

2nd Map to Map on details

reduce to convert nested array to single array

%dw 2.0
output application/json
---
payload map(
    ($.details map(item,index)->{
        "name":($.name),
        "num":item[0]
    })
)reduce($$++$)

Output

[
  {
    "name": "Thinker",
    "num": 1
  },
  {
    "name": "Thinker",
    "num": 2
  },
  {
    "name": "Blinker",
    "num": 3
  },
  {
    "name": "Blinker",
    "num": 4
  }
]

DW

%dw 2.0
output application/json
---
payload map(
    ($.details map(item,index)->{
        (keysOf($)[0]):($.name),
        (keysOf(item)[0]):item[0]
    })
)reduce($$++$)
Karthik
  • 2,181
  • 4
  • 10
  • 28
  • Great answer. Is there a way to avoid writing the "name" and "num" Inside the main code and make it as a function and make the function construct field names by itself? – Thinker-101 Mar 04 '22 at 15:40
  • 1
    @Thinker-101 Modified answer. Does that help? Construct name by itself on what basis?? – Karthik Mar 04 '22 at 15:45
1

If your request structure will always remain this way(regardelss of field names), then you can try this script as below, that is more genric and will work on same type of strucure

%dw 2.0
output application/json
---
payload flatMap ((item, index) -> 
   (item filterObject ($ is Array))[0] map 
                 ($ ++ (item filterObject ($ is String | Number | Null)) )
 
)

Note: it can work on this type of structure always and not depend on field names, and gives expected output

[{
  "anyname": "xyz",
  "anydetails": [
      {
      "abc": 1
      }, 
      {
      "ijk": 2
      }
   ]
}]

Anurag Sharma
  • 780
  • 7
  • 31