Есть ли ошибки в моем коде при использовании оценки в Groovy? - PullRequest
0 голосов
/ 06 апреля 2019

Я устанавливаю значение для вложенной карты, все ключи существуют, вот мой код:

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 = 'test'" Я могу запустить его вручную, и содержимое карты изменяется, но когда я использую метод оценки, возникает ошибка "java.lang.NullPointerException: не удается получить свойство 'b2' для нулевого объекта". Скажите, пожалуйста, что не так с кодом Спасибо большое.

Ответы [ 2 ]

1 голос
/ 06 апреля 2019

То, что вы пытаетесь сделать, сложно ...

Один из методов - использовать Eval.x и передать карту как x:

def setValue(Map map, String[] keys, String data) {
    def command = "x.${keys.join('.')} = '$data'"
    Eval.x(map, command)
}

Итак, команда будет выглядеть так: 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'

Который затем печатает имя пользователя ... Вы можете увидеть, как это может быть адаптировано для загрузки файла из Интернета и размещения его на чьей-то машине ...

Если вы можете ... Вам следует избегать этого ... Или, по крайней мере, иметь строгие белые списки того, что разрешено

0 голосов
/ 06 апреля 2019

рекурсивный подход:

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)
}
...