Freemarker имеет два типа данных коллекций: списки и хэш-карты. Есть ли способ перебирать ключи хэш-карты, как мы это делаем со списками?
Итак, если у меня есть переменная с данными, скажем:
user : {
name : "user"
email : "looser@everything.com"
homepage : "http://nosuchpage.org"
}
Я хочу напечатать все свойства пользователя с их значением. Это неверно, но цель ясна:
<#list user.props() as prop>
${prop} = ${user.get(prop)}
</#list>
java
freemarker
цадор
источник
источник
${user[prop]}
как стенографиюuser[prop]
работают, насколькоprop
это возможноString
(в противном случае вам нужноuser?api.get(prop)
сейчас), но будьте осторожны, некоторые фреймворки (например, Struts, я считаю) используют теперь устаревшую настройку, где имена методов смешаны сMap
ключами, и поэтому, если значениеprops
происходит с быть именем метода вuser
объекте Java, вы получите метод вместо того, что имели в виду. Вот почему они всегда используют эти устаревшие установкиuser.get(prop)
.FYI, похоже, что синтаксис для получения значений изменился в соответствии с:
http://freemarker.sourceforge.net/docs/ref_builtins_hash.html
<#assign h = {"name":"mouse", "price":50}> <#assign keys = h?keys> <#list keys as key>${key} = ${h[key]}; </#list>
источник
[key]
и другое.get(key)
существует с давних времен..get(key)
не является чем-то особенным для FTL, он просто вызывает этот общедоступный метод Java. Но вы можете использовать его, только если FreeMarker был настроен для предоставленияMap
методов.Начиная с 2.3.25, делайте это так:
Обратите внимание, что это также работает с нестроковыми ключами (в отличие от того
map[key]
, что нужно было записать какmap?api.get(key)
тогда).До 2.3.25 стандартным решением было:
Однако некоторые действительно старые интеграции FreeMarker используют странную конфигурацию, в которой общедоступные
Map
методы (например,getClass
) отображаются как ключи. Это происходит, когда они используют чистыйBeansWrapper
(вместоDefaultObjectWrapper
),simpleMapWrapper
свойство которого было оставленоfalse
. Вам следует избегать такой настройки, поскольку она смешивает методы с реальнымиMap
записями. Но если вы столкнетесь с такой неудачной настройкой, способ избежать ситуации - использовать открытые методы Java, такие какuser.entrySet()
,user.get(key)
и т.д., а не использовать конструкции языка шаблонов, такие как?keys
илиuser[key]
.источник
${x?nosuchthing}
и наведете на него курсор, в отображаемом сообщении об ошибке будет указано, какую версию FreeMarker он использует. Так и должно быть2.3.25-incubating
.Если вы используете BeansWrapper с уровнем раскрытия Expose.SAFE или Expose.ALL, то можно использовать стандартный Java-подход к итерации набора записей:
Например, в Freemarker (начиная с версии 2.3.19) будет работать следующее:
<#list map.entrySet() as entry> <input type="hidden" name="${entry.key}" value="${entry.value}" /> </#list>
В Struts2, например, используется расширение BeanWrapper с установленным по умолчанию уровнем раскрытия, чтобы разрешить этот способ итерации.
источник
InvalidReferenceException
когда пробовал, покаmap?keys
работал.freemarker.ext.beans.BeansWrapper
качестве оболочки объекта. В противном случаеMap
s будет автоматически заключен вSimpleHash
объект, который не поддерживает#entrySet()
. (см. freemarker.sourceforge.net/docs/api/freemarker/template/… )BeansWrapper
, по крайней мере, с его значениями по умолчанию, гдеsimpleMapWrapper
естьfalse
. Это очень сбивает с толку, так как смешивает ключи с именами методов. Если вам нужно вызватьentrySet()
, просто продолжайте использовать «чистую» обертку объекта, такую как стандартная, и напишите,map?api.entrySet()
если вам нужен доступ к Java API вместо ключей.Итерация объектов
Если ваши ключи карты являются объектом, а не строкой, вы можете выполнить итерацию с помощью Freemarker.
1) Преобразуйте карту в список в контроллере:
List<Map.Entry<myObjectKey, myObjectValue>> convertedMap = new ArrayList(originalMap.entrySet());
2) Итерируйте карту в шаблоне Freemarker, обращаясь к объекту в Ключе и Объекту в Значении:
источник
Для полноты картины стоит упомянуть, что с недавнего времени в Freemarker появилась достойная обработка пустых коллекций.
Итак, наиболее удобный способ перебора карты:
<#list tags> <ul class="posts"> <#items as tagName, tagCount> <li>{$tagName} (${tagCount})</li> </#items> </ul> <#else> <p>No tags found.</p> </#list>
Нет больше
<#if ...>
оберток.источник
Вы можете использовать одинарные кавычки для доступа к ключу, который вы установили в своей программе Java.
Если вы установите карту в Java следующим образом
Map<String,Object> hash = new HashMap<String,Object>(); hash.put("firstname", "a"); hash.put("lastname", "b"); Map<String,Object> map = new HashMap<String,Object>(); map.put("hash", hash);
Затем вы можете получить доступ к членам 'hash' в Freemarker следующим образом:
${hash['firstname']} ${hash['lastname']}
Выход :
источник