You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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节点

原代码生成的结果存在两个核心问题:

  1. 各级hierarchy应为数组,但实际生成的是对象
  2. 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)
        }
    })

关键修正点

  1. 层级结构从对象转数组:使用pluck将分组后的对象转换为数组,确保hierarchy字段始终是数组类型
  2. 简化分组逻辑:提取通用的分组函数,避免重复判断层级的分组规则
  3. 明确跳过父节点的逻辑:在顶层和递归中直接判断是否需要跳过Parent层,直接递归到Child层
  4. 拆分节点构建逻辑:将单个节点的结构封装为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 04:55:33