使用字符串表示法的Groovy对象检索

使用字符串表示法的Groovy对象检索,groovy,Groovy,使用groovy为Jenkins管道编写了一个实用方法,并注意到使用外部对象检索符号作为字符串从深度嵌套的映射中获取值并不容易 问题:如果您看到下面的示例,您会注意到无法检索表单数据中的对象。“bankctrl.deployment.clientConfigMap.enabled”。您肯定可以进行数据处理。“bankctrl”“部署”“clientConfigMap”“已启用”。我有一个变通方法,但问题是是否有任何已知的最佳方法来做到这一点 datas = [ "ao"

使用groovy为Jenkins管道编写了一个实用方法,并注意到使用外部对象检索符号作为字符串从深度嵌套的映射中获取值并不容易

问题:如果您看到下面的示例,您会注意到无法检索表单数据中的对象。“bankctrl.deployment.clientConfigMap.enabled”。您肯定可以进行数据处理。“bankctrl”“部署”“clientConfigMap”“已启用”。我有一个变通方法,但问题是是否有任何已知的最佳方法来做到这一点

datas = [
    "ao":[
        deployment:[
            clientConfigMap:[
                enabled:"true", name:"volume-ao-custom"
            ], image:[
                name:"test/mit/ao", 
                tag:"10.0.0-3.0.0", 
                pullPolicy:"IfNotPresent"
            ]
        ]
    ], "bankctrl":[
        deployment:[
            clientConfigMap:[
                enabled:"false", 
                name:"volume-bankctrl-custom"
            ], image:[
                name:"test/mit/bankctrl", 
                tag:"10.0.0-3.0.0", 
                pullPolicy:"IfNotPresent"
            ]
        ]
    ]
]

String name = "bankctrl"
datas."${name}".deployment.clientConfigMap.enabled = true

println datas

//following does't work as dots within string are not evaluated.
String elementNameToUpdate = "bankctrl.deployment.clientConfigMap.enabled"
datas."${elementNameToUpdate}" = true
当您需要使用外部化字符串访问值时,以下代码起作用:

String s = "bankctrl.deployment.clientConfigMap.enabled"

def q = s.split( /\./ ).inject( datas ) { obj1, prop -> obj1?."$prop" }

println q
String s = "bankctrl.deployment.clientConfigMap.enabled"
Eval.x(datas,"x.${s}")
当您需要使用外部化字符串访问值时,此功能也可以工作:

String s = "bankctrl.deployment.clientConfigMap.enabled"

def q = s.split( /\./ ).inject( datas ) { obj1, prop -> obj1?."$prop" }

println q
String s = "bankctrl.deployment.clientConfigMap.enabled"
Eval.x(datas,"x.${s}")
一种解决方法

String s = "bankctrl.deployment.clientConfigMap.enabled"

def setDeepProps(s,datas, value) {

    s.split(/\./).inject(datas) {
        obj, prop ->
            if (obj."$prop" instanceof Map)
                obj?."$prop"
            else
                obj."$prop" = value
    }
}

setDeepProps(s,datas,true)

println datas

Groovy没有现成的这一功能,因此您必须任意使用
Eval
:),在这种情况下,它有点脆弱(如果路径字符串拼写错误,可能会产生运行时异常),并且不是最佳执行者(由于运行时编译)

您可以通过以下简单的递归来解决问题:

def datas = [
    "ao":[
        deployment:[
            clientConfigMap:[
                enabled:"true", name:"volume-ao-custom"
            ], image:[
                name:"test/mit/ao",
                tag:"10.0.0-3.0.0",
                pullPolicy:"IfNotPresent"
            ]
        ]
    ], "bankctrl":[
        deployment:[
            clientConfigMap:[
                enabled:"false",
                name:"volume-bankctrl-custom"
            ], image:[
                name:"test/mit/bankctrl",
                tag:"10.0.0-3.0.0",
                pullPolicy:"IfNotPresent"
            ]
        ]
    ]
]

def traverser

traverser = { map, path ->
  int ix = path.indexOf '.'
  if( -1 == ix ) return map[ path ]
  
  def val = map[ path[ 0..<ix ] ]
  if( val in Map )
    traverser val, path.substring( ix + 1 )
  else
    null
}

traverser datas, "bankctrl.deployment.clientConfigMap.enabled"
def数据=[
“ao”:[
部署:[
clientConfigMap:[
启用:“真”,名称:“卷ao自定义”
],图片:[
名称:“test/mit/ao”,
标签:“10.0.0-3.0.0”,
pullPolicy:“如果不存在”
]
]
],“bankctrl”:[
部署:[
clientConfigMap:[
启用:“假”,
名称:“卷库控制自定义”
],图片:[
名称:“test/mit/bankctrl”,
标签:“10.0.0-3.0.0”,
pullPolicy:“如果不存在”
]
]
]
]
def遍历器
遍历器={map,path->
int ix=path.indexOf''
if(-1==ix)返回映射[路径]

def val=map[path[0..下面的变通方法对我来说很有效。我之所以喜欢这种方法而不是其他解决方案,是因为Jenkins对您调用的脚本非常挑剔,因此希望有一种变通方法,在绕过此要求时不会强迫我接受Jenkins中的脚本执行

顺便说一句,如果Jenkins允许我探索Groovy的全部功能,我会很高兴,但不幸的是,出于安全原因,它没有

datas = [
    "ao":[
        deployment:[
            clientConfigMap:[
                enabled:"false", 
                name:"volume-ao-custom"
            ], image:[
                name:"test/mit/ao", 
                tag:"10.0.0-3.0.0", 
                pullPolicy:"IfNotPresent"
            ]
        ]
    ], "bankctrl":[
        deployment:[
            clientConfigMap:[
                enabled:"false", 
                name:"volume-bankctrl-custom"
            ], image:[
                name:"test/mit/bankctrl", 
                tag:"10.0.0-3.0.0", 
                pullPolicy:"IfNotPresent"
            ]
        ]
    ]
]

boolean customConfigFolderExists = true
String elementNameToUpdate = "bankctrl.deployment.clientConfigMap.enabled"

String[] elementNameToUpdateArray = "${elementNameToUpdate}".split("\\.")
                                                        
def tempDatas = datas

//get property like datas.bankctrl.deployment.clientConfigMap (note that we are leaving enabled out which would be invoked in the following steps)
for (int i=0; i<elementNameToUpdateArray.length-1; i++) {
    println "elementNameToUpdateArray[i] -> ${elementNameToUpdateArray[i]}"
    tempDatas = tempDatas?."${elementNameToUpdateArray[i]}"
}

//we are invoking property returned from for loop above using the last element from elementNameToUpdateArray 
tempDatas?."${elementNameToUpdateArray[elementNameToUpdateArray.length-1]}" = true

println "datas = ${datas}"
datas=[
“ao”:[
部署:[
clientConfigMap:[
启用:“假”,
名称:“卷ao自定义”
],图片:[
名称:“test/mit/ao”,
标签:“10.0.0-3.0.0”,
pullPolicy:“如果不存在”
]
]
],“bankctrl”:[
部署:[
clientConfigMap:[
启用:“假”,
名称:“卷库控制自定义”
],图片:[
名称:“test/mit/bankctrl”,
标签:“10.0.0-3.0.0”,
pullPolicy:“如果不存在”
]
]
]
]
布尔值customConfigFolderExists=true
String elementNameToUpdate=“bankctrl.deployment.clientConfigMap.enabled”
字符串[]elementNameToUpdateArray=“${elementNameToUpdate}”。拆分(“\\”)
def tempDatas=datas
//获取类似datas.bankctrl.deployment.clientConfigMap的属性(请注意,我们将在下面的步骤中调用的属性省略为enabled)

对于(int i=0;i),问题是?如何使以下内容起作用。请注意elementNameToUpdate是字符串而不是点表示法。string elementNameToUpdate=“bankctrl.deployment.clientConfigMap.enabled”datas.${elementNameToUpdate}”=trueUse eval.me-有什么问题?