如何用DataWeave动态展平嵌套JSON对象(适配多结构Payload)
DataWeave实现动态键适配的JSON笛卡尔积转换
需求说明
需要将输入JSON中Report_Entry条目下的非数组属性,与所有数组类型属性的元素进行笛卡尔积组合,生成平铺的对象数组。要求支持动态键适配——不管输入中数组类型的字段叫什么(比如示例中的Lines、Amendments),都能自动识别并参与笛卡尔积计算,无需硬编码字段名。
输入示例
{ "Report_Entry": [ { "Accepted_Currencies": "USD; EUR", "Amount": "22", "Lines": [{"Project": "Proj1"}, {"Project": "Proj2"}], "Amendments": [{"Name": "Amd 1", "Status": "Approved"}, {"Name": "Amd 2", "Status": "Approved"}] } ] }
输出示例
[ {"Accepted_Currencies": "USD; EUR", "Amount": "22", "Project": "Proj1", "Name": "Amd 1", "Status": "Approved"}, {"Accepted_Currencies": "USD; EUR", "Amount": "22", "Project": "Proj1", "Name": "Amd 2", "Status": "Approved"}, {"Accepted_Currencies": "USD; EUR", "Amount": "22", "Project": "Proj2", "Name": "Amd 1", "Status": "Approved"}, {"Accepted_Currencies": "USD; EUR", "Amount": "22", "Project": "Proj2", "Name": "Amd 2", "Status": "Approved"} ]
解决方案(DataWeave 2.0)
完整转换代码
%dw 2.0 output application/json // 递归实现任意数量数组的笛卡尔积 fun crossJoin(arrays: Object): Array<Object> = arrays match { // 终止条件:无数组时返回空对象数组 case {} => [{}] // 递归拆分:取第一个数组,和剩余数组的笛卡尔积做flatMap组合 case { first: var arr, rest: var remainingArrays } => arr flatMap (item) -> crossJoin(remainingArrays) map (crossItem) -> item ++ crossItem } --- // 遍历每个Report_Entry条目 payload.Report_Entry flatMap (entry) -> do { // 1. 提取非数组类型的基础属性 var baseProps = entry filterObject ((val, key) -> !isArray(val)) // 2. 提取所有数组类型的字段值(保留元素原结构) var arrayCollections = entry filterObject ((val, key) -> isArray(val)) // 3. 对所有数组做笛卡尔积 var crossCombined = crossJoin(arrayCollections) } // 4. 每个笛卡尔积组合与基础属性合并,生成最终对象 crossCombined map (combined) -> baseProps ++ combined
代码解释
crossJoin递归函数:- 核心功能是处理任意数量的数组,生成它们的笛卡尔积组合。
- 通过模式匹配拆分数组集合,递归计算剩余数组的笛卡尔积,再与当前数组的每个元素做扁平化组合。
主转换逻辑:
baseProps:筛选出当前Report_Entry中所有非数组的属性(比如示例里的Accepted_Currencies、Amount),作为每个结果对象的固定部分。arrayCollections:筛选出所有数组类型的字段(比如Lines、Amendments),这些是需要做笛卡尔积的维度。crossCombined:调用crossJoin得到所有数组元素的笛卡尔积组合。- 最后将每个组合与
baseProps合并,得到平铺的结果对象。
动态适配特性:
- 代码中没有硬编码任何数组字段名,完全通过
isArray()判断识别数组字段。 - 如果输入中新增其他数组字段(比如
Items: [{"SKU": "A1"}, {"SKU": "A2"}]),代码会自动将其纳入笛卡尔积计算,无需修改逻辑。
- 代码中没有硬编码任何数组字段名,完全通过
内容的提问来源于stack exchange,提问作者Ayyappa P
相关产品推荐
相关产品推荐

