Я не могу заставить #evaluate установить переменную, используя какое-либо принятое решение, которое я видел для преобразования строки JSON в карту с использованием Velocity в Confluence.
У меня есть строка JSON из другой системы, которую я использую для генерации динамических данных. Во время разработки я смог работать с картой напрямую:
#set($textMapRaw = [{"ace":"clubs"}])
$textMapRaw.get(0).ace
Последняя строка отображается как «трефы».
Я ожидал использовать #evaluate, чтобы превратить живые данные в массив объектов. Однако кажется, что #evaluate не возвращает объявленную переменную в область видимости, когда я что-то с ней делаю. Вот та же карта, представленная в виде строки:
#set($textMapHtml = '[{"ace":"clubs"}]')
#set($evalHtml = '#set($myMapHtml = '+ $textMapHtml +')')
evalHtml = $evalHtml<br/>
#evaluate($evalHtml)
$myMapHtml.get(0).ace
Последняя строка отображается как «$myMapHtml.get(0).ace».
Я знаю, что $myMapHtml оценивается, потому что я получал оценочную трассировку стека, когда не добавлял Html
в конец, чтобы избежать махинаций Confluence с автоматическим экранированием.
Я пробовал это с экранированием хэша в наборе, используя ${hash}set. Я пробовал одинарные кавычки и двойные кавычки. Я пробовал это, просто установив строку с помощью оценки:
#evaluate('#set($dippity = "doo")')
$dippity
#set($hash = '#')
#evaluate("${hash}set($blue = 'moon')")
$blue
Что бы я ни делал с любым ратифицированным кодом #evaluate, он никогда не оценивается в Confluence. Я всегда получаю результат, идентичный неопределенной переменной.
Примечание. В нашей среде я не могу найти обходной путь на Java и вставить его в шаблон. Мне нужно найти чистое решение в шаблоне.
Вы делаете это в Confluence? Вот в чем хитрость. Я считаю, что Confluence 6.13 использует Velocity 1.6.4. Но, похоже, это проблема с Confluence.
Velocity 1.6.4 не позволяет изменять контекст оценки из директивы #evaluate
. Поэтому при использовании этой версии невозможно создавать записи контекста с динамическим именем.
Однако вы можете сохранить их на карте:
#set( $stringMap = '[{"ace":"clubs"}]' )
#set( $myMap = {} )
#set( $eval = '#set($list = ' + $stringMap + ') #set ($myMap.ace =
$list.get(0).ace)' )
#evaluate( $eval )
$myMap.ace ## prints 'clubs'
В строке 2 есть ошибка, потому что вы не поместили одноразовую переменную для директивы set/put. Добавление этого и запуск кода не достигают цели превращения строки в повторяемый массив карт. значение HTML является строкой.
@Kevin - отредактировано в соответствии с вашими комментариями. Но, видя ваш ответ, очевидно, вы его поняли...
Спасибо, что избавили меня от дальнейших попыток вернуть переменную в глобальную область видимости.
Поскольку кажется, что вы не можете вернуть переменную в текущую область, я нашел обходной путь. Просто используйте оценку, чтобы передать массив/карту в макрос.
Вы по-прежнему сталкиваетесь с проблемами области видимости, если пытаетесь манипулировать переменными за пределами вычисляемого кода или макроса, который он вызывает, но если вы будете осторожны, вы можете обойти это.
В моем случае я переместил еще один фрагмент кода внутрь макроса, чтобы воспользоваться преимуществами локальной области видимости и определить, сколько элементов было обработано.
#macro(processMap $theMap)
#set($count = 0)
#foreach($item in $theMap)
#set($count = $velocityCount)
<p>This thing is $item.tweedle</p>
#end
<p><b>I did that $count times</b></p>
#end
#set($workaroundHtml = '[{"tweedle":"dee"},{"tweedle":"dum"}]')
#set($eval = '#processMap(' + $workaroundHtml + ')')
#evaluate($eval)
Если я скопирую и вставлю ваш код в свою тестовую среду, используя Velocity 1.7 или 2.0, он будет работать... Какую версию Velocity вы используете?