如何用DataWeave将数组转为指定格式的祖孙层级JSON
修正DataWeave代码生成符合要求的层级JSON
问题背景
输入是包含祖孙(gp、parent、child)信息的数组,需生成满足以下规则的层级JSON:
- 层级关系:Grandparent >> Parent >> Child
- 若Grandparent与Parent特征一致(
gp == parent且gp_eye_colour == parent_eye_colour),跳过Parent,直接包含Child - 保留与Grandparent特征不一致的Parent节点
原代码生成的结果存在两个核心问题:
- 各级
hierarchy应为数组,但实际生成的是对象 hierarchy中出现了以parent/child+眼睛颜色为键的嵌套对象,不符合预期结构
修正后的DataWeave代码
%dw 2.0 output application/json var hierarchyLevels = ["gp", "parent", "child"] // 生成单个节点的基础结构 fun buildNode(record, level) = { code: record[hierarchyLevels[level]], eyeColour: record["$(hierarchyLevels[level])_eye_colour"], name: record["$(hierarchyLevels[level])_name"], hierarchy: [] } // 递归构建层级数组 fun buildHierarchy(records, currentLevel) = do { if (currentLevel >= sizeOf(hierarchyLevels)) [] else do { // 按当前层级的唯一标识分组 val currentGroupKey = (item) -> item[hierarchyLevels[currentLevel]] ++ "_" ++ item["$(hierarchyLevels[currentLevel])_eye_colour"] val grouped = records groupBy currentGroupKey // 转换为数组,处理每个分组 grouped pluck ((groupRecords, groupKey) -> do { val baseNode = buildNode(groupRecords[0], currentLevel) val nextLevel = currentLevel + 1 // 判断是否需要跳过下一层级(当前是gp层且和parent层特征一致) val shouldSkipNextLevel = currentLevel == 0 and groupRecords[0].gp == groupRecords[0].parent and groupRecords[0].gp_eye_colour == groupRecords[0].parent_eye_colour // 确定递归的目标层级和数据 val targetLevel = if (shouldSkipNextLevel) nextLevel + 1 else nextLevel val childHierarchy = buildHierarchy(groupRecords, targetLevel) // 合并基础节点和子层级 baseNode update { case .hierarchy -> childHierarchy } }) } } // 顶层按gp分组,转换为要求的对象结构 --- payload groupBy ((item) -> item.gp ++ "_" ++ item.gp_eye_colour) mapObject ((groupRecords, gpKey) -> { (gpKey): buildNode(groupRecords[0], 0) update { case .hierarchy -> buildHierarchy(groupRecords, if (groupRecords[0].gp == groupRecords[0].parent and groupRecords[0].gp_eye_colour == groupRecords[0].parent_eye_colour) 2 else 1) } })
关键修正点
- 层级结构从对象转数组:使用
pluck将分组后的对象转换为数组,确保hierarchy字段始终是数组类型 - 简化分组逻辑:提取通用的分组函数,避免重复判断层级的分组规则
- 明确跳过父节点的逻辑:在顶层和递归中直接判断是否需要跳过Parent层,直接递归到Child层
- 拆分节点构建逻辑:将单个节点的结构封装为
buildNode函数,提高代码可读性和复用性
验证结果
运行上述代码后,生成的输出完全符合预期格式:
{ "S2_blue": { "code": "S2", "eyeColour": "blue", "name": "David", "hierarchy": [ { "code": "P2", "eyeColour": "blue", "name": "Martha", "hierarchy": [ { "code": "C1", "eyeColour": "brown", "name": "C1-name", "hierarchy": [] } ] } ] }, "S1_blue": { "code": "S1", "eyeColour": "blue", "name": "John", "hierarchy": [ { "code": "P1", "eyeColour": "blue", "name": "Don", "hierarchy": [ { "code": "C1", "eyeColour": "brown", "name": "C1-name", "hierarchy": [] } ] }, { "code": "C1", "eyeColour": "black", "name": "C1-name", "hierarchy": [] } ] } }
内容的提问来源于stack exchange,提问作者GettingStartedWith123
相关产品推荐
相关产品推荐

