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

无JSONSlurper的Groovy JSON与YAML合并:ArrayList处理及引用问题

Jenkins中LinkedHashMap递归合并的原理解析与优化

一、递归合并函数的核心执行逻辑

你用readJSON拿到的LinkedHashMap,本质是Groovy基于Java实现的键值对容器,递归合并函数的核心逻辑是以原JSON的Map为基础,用YAML配置的Map逐层覆盖/补充,执行流程如下:

  1. 遍历YAML配置Map(override)的每一个键值对
  2. 检查原JSON Map(base)中是否存在相同的键:
    • 如果键对应的值都是Map类型,就递归调用合并函数处理这两个子Map,把返回的新Map存入结果
    • 如果是字符串、数字等普通类型,直接用YAML的值覆盖原JSON的值
    • 如果是List类型,需要单独做结构保留处理(这也是你原函数出问题的核心点)

你之前疑惑的「传入两个Map后如何循环?结果如何存入result?两个Map如何关联?」,其实是函数先创建一个基于base的结果容器(或直接操作base),然后循环override的所有键,通过相同键关联两个Map的内容,把处理后的键值对逐个放入result中,用override的内容更新base的对应项。

二、原函数ArrayList丢失方括号的问题解析

你遇到的WriteTo后方法括号丢失,本质是原函数没有正确识别List类型,导致List结构被破坏:

  • 比如原函数可能没有判断值是否为ArrayList,直接把YAML中的List元素当成单个值赋值,或者错误地对List执行了Map的遍历操作(List没有键,遍历会直接拆解元素)
  • 举个例子:如果原JSON中WriteTo是["file1.txt"],YAML中是["file2.txt"],原函数如果没处理List类型,可能会把值改成file2.txt(去掉方括号,变成字符串类型)

三、引用传递导致原变量被修改的原因及优化方案

Groovy中对象(比如LinkedHashMap、ArrayList)是引用传递,如果你的修改后的函数直接操作base的元素(比如base.put(key, value)),就会直接改变原输入变量的值——因为你操作的是同一个内存地址的对象。

优化后的递归合并函数

下面是避免修改原变量、正确处理List的优化版本:

def mergeMaps(def base, def override) {
    // 创建新的LinkedHashMap,基于base的副本,彻底隔离原对象
    def result = new LinkedHashMap(base)
    
    override.each { key, value ->
        if (result.containsKey(key)) {
            def baseValue = result.get(key)
            // 嵌套Map递归合并
            if (baseValue instanceof Map && value instanceof Map) {
                result.put(key, mergeMaps(baseValue, value))
            }
            // List处理:此处为合并两个List元素,若需替换可改为new ArrayList(value)
            else if (baseValue instanceof List && value instanceof List) {
                def mergedList = new ArrayList(baseValue)
                mergedList.addAll(value)
                result.put(key, mergedList)
            }
            // 普通类型直接覆盖
            else {
                result.put(key, value)
            }
        } else {
            // base中没有的键直接添加到结果
            result.put(key, value)
        }
    }
    return result
}

优化点说明

  1. 隔离原对象:每次合并都创建新的LinkedHashMap和ArrayList,所有操作都在新对象上进行,彻底避免修改原输入变量
  2. 明确List处理策略:根据业务需求选择合并(addAll)或替换(直接赋值新List),确保List结构不会丢失
  3. 类型安全校验:通过instanceof判断值的类型,避免因类型不匹配导致的异常或结构错误
  4. 无副作用:函数执行后,原base和override变量不会被修改,符合纯函数的设计原则

额外建议

  • 如果需要处理空值场景,可以在函数开头添加判断:比如if (!base) return new LinkedHashMap(override),避免空指针异常
  • 若YAML中的List是要完全替换原JSON的List,把List处理部分改成result.put(key, new ArrayList(value))即可

内容的提问来源于stack exchange,提问作者dejavized

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 12:33:18