在groovy中使用evaluate时,我的代码中有错误吗?

在groovy中使用evaluate时,我的代码中有错误吗?,groovy,evaluate,Groovy,Evaluate,我将值设置为嵌套贴图,所有键都存在,以下是我的代码: def map = [a1:[a2:[a3:'a123']], b1:[b2:[b3_1:'b234', b3_2:'b345']], d1:'d1'] def name2 = "b1:::b2:::b3_1" def data = "test" def separator = ":::" def names = name2.split(separator) setValue(map, names, data) def setValue

我将值设置为嵌套贴图,所有键都存在,以下是我的代码:

def map = [a1:[a2:[a3:'a123']], b1:[b2:[b3_1:'b234', b3_2:'b345']], d1:'d1']
def name2 = "b1:::b2:::b3_1"
def data = "test"
def separator = ":::"

def names = name2.split(separator)

setValue(map, names, data)

def setValue(def map, def keys, def data) {
    tmpMap = map
    String str = 'map' 
    for (i = 0; i < keys.size(); i++) {
        str = str.concat('.'+ keys[i])
    }
    str = str.concat(" = '" + data + "'")

    evaluate(str)
}
str内容将为map.b1.b2.b3_1=‘测试’
我可以手动运行它并更改地图内容,但是当我使用evaluate时,出现了java.lang.NullPointerException错误:无法在null对象上获取属性“b2”,请告诉我代码有什么问题,非常感谢。

您试图做的很难

一种方法是使用Eval.x,并将地图作为x传递:

这里的命令是:x.b1.b2.b3_1='test',我们用x作为map的值来计算它

另一个更难看的方法是使用inject遍历贴图直到最后一个键,然后设置此返回对象的最后一个键的值:

def setValue(Map map, String[] keys, String data) {
    keys[0..-2].inject(map) { a, b -> a."$b" }."${keys[-1]}" = data
}
不过,您应该警惕随意评估代码

例如,您可能会收到以下输入:

def name2 = "val = { -> println \"${System.properties.'user.name'}\" }.call(); def a"
为我计算表达式:

x.val = { -> println "tim" }.call(); def a = 'test'
然后打印用户名。。。您可以看到如何将其改编为从internet下载文件并将其放在某人的机器上

如果你能。。。你应该避免这个。。。或者至少有严格的白名单,列出允许的递归方法:

def setValue(def map, List keys, def data) {
    return keys.size()>1 ? 
        setValue(map[keys[0]],keys.subList(1,keys.size()),data) : 
            map.put(keys[0],data)
}

您好,您的想法很好,但结果不是我想要的,我尝试了,返回值是B234。它返回地图中的旧值。并修改地图。你可以检查一下。我很抱歉这么长时间没有回复,你是对的,它成功地解决了我的问题,非常感谢!谢谢你们的回复,我尝试了你们的第一种方法,它很有效,正如你们所说,它看起来有点难看,所以我用递归方法来解决它,谢谢你们的帮助!
def setValue(def map, List keys, def data) {
    return keys.size()>1 ? 
        setValue(map[keys[0]],keys.subList(1,keys.size()),data) : 
            map.put(keys[0],data)
}