使用DataWeave将含可选子元素的JSON多维数组转一维数组
Got it, let's tackle this problem step by step. You need to flatten a nested JSON array where parent attributes repeat for each child, and handle cases where some parents don't have children. Plus, avoiding hardcoding every attribute name makes total sense for hundreds of fields. Here's how to do it with DataWeave 2.x:
Scenario 1: Keep All Attributes
First, let's handle full attribute flattening. The key here is using flatMap to iterate over each parent, then either expanding its children into individual entries (merging parent and child attributes) or returning the parent itself if there are no children. We'll use merge to combine objects automatically—no need to list every attribute!
Input Payload
[ { "id": "1", "parentAttribute1": "parent1-1", "parentAttribute2": "parent1-2", "parentAttribute3": "parent1-3", "child": [ { "childAttribute1": "inner1-1-1", "childAttribute2": "inner1-1-2" }, { "childAttribute1": "inner1-2-1", "childAttribute2": "inner1-2-2" }, { "childAttribute1": "inner1-3-1", "childAttribute2": "inner1-3-2" } ] }, { "id": "2", "parentAttribute1": "parent2-1", "parentAttribute2": "parent2-2", "parentAttribute3": "parent2-3", "child": [ { "childAttribute1": "inner2-1-1", "childAttribute2": "inner2-1-2" } ] }, { "id": "3", "parentAttribute1": "parent3-1", "parentAttribute2": "parent3-2", "parentAttribute3": "parent3-3" } ]
DataWeave Script
%dw 2.0 output application/json --- payload flatMap (parent) -> if (parent.child != null and sizeOf(parent.child) > 0) parent.child map (child) -> (parent - "child") merge child else [parent]
How It Works
flatMapprocesses each parent object: if it has children, it expands them into separate entries; if not, it returns the parent as a single entry.parent - "child"removes the child array from the parent so we don't include it in the flattened result.mergeautomatically combines the parent's attributes (minus the child array) with each child's attributes—no manual field mapping required.- The
ifcondition handles parents without achildarray gracefully.
Output (Matches Scenario 1)
[ { "id": "1", "parentAttribute1": "parent1-1", "parentAttribute2": "parent1-2", "parentAttribute3": "parent1-3", "childAttribute1": "inner1-1-1", "childAttribute2": "inner1-1-2" }, { "id": "1", "parentAttribute1": "parent1-1", "parentAttribute2": "parent1-2", "parentAttribute3": "parent1-3", "childAttribute1": "inner1-2-1", "childAttribute2": "inner1-2-2" }, { "id": "1", "parentAttribute1": "parent1-1", "parentAttribute2": "parent1-2", "parentAttribute3": "parent1-3", "childAttribute1": "inner1-3-1", "childAttribute2": "inner1-3-2" }, { "id": "2", "parentAttribute1": "parent2-1", "parentAttribute2": "parent2-2", "parentAttribute3": "parent2-3", "childAttribute1": "inner2-1-1", "childAttribute2": "inner2-1-2" }, { "id": "3", "parentAttribute1": "parent3-1", "parentAttribute2": "parent3-2", "parentAttribute3": "parent3-3" } ]
Scenario 2: Keep Only Selected Attributes
For this case, we can define lists of parent and child attributes to retain, then filter both objects before merging. This keeps the script scalable even if you need to adjust the selected fields later.
DataWeave Script
%dw 2.0 output application/json var parentAttributesToKeep = ["id", "parentAttribute1"] var childAttributesToKeep = ["childAttribute1"] --- payload flatMap (parent) -> if (parent.child != null and sizeOf(parent.child) > 0) parent.child map (child) -> (parent filterObject ((value, key) -> parentAttributesToKeep contains key)) merge (child filterObject ((value, key) -> childAttributesToKeep contains key)) else [parent filterObject ((value, key) -> parentAttributesToKeep contains key)]
How It Works
- We define
parentAttributesToKeepandchildAttributesToKeepas arrays of the attribute names we want to retain. filterObjectnarrows down both parent and child objects to only the specified fields before merging.- The core
flatMaplogic remains the same as Scenario 1, ensuring consistent handling of parents with or without children.
Output (Matches Scenario 2)
[ { "id": "1", "parentAttribute1": "parent1-1", "childAttribute1": "inner1-1-1" }, { "id": "1", "parentAttribute1": "parent1-1", "childAttribute1": "inner1-2-1" }, { "id": "1", "parentAttribute1": "parent1-1", "childAttribute1": "inner1-3-1" }, { "id": "2", "parentAttribute1": "parent2-1", "childAttribute1": "inner2-1-1" }, { "id": "3", "parentAttribute1": "parent3-1" } ]
This approach scales easily for hundreds of attributes—just add the names to the respective arrays in Scenario 2, or use the first script for full attribute retention. No manual field mapping needed!
内容的提问来源于stack exchange,提问作者kimmy

