Freemarker tiene dos tipos de datos de colección, listas y hashmaps. ¿Hay alguna forma de iterar sobre las claves de hashmap como lo hacemos con las listas?
Entonces, si tengo una var con datos, digamos:
user : {
name : "user"
email : "[email protected]"
homepage : "http://nosuchpage.org"
}
Me gustaría imprimir todas las propiedades del usuario con su valor. Esto no es válido, pero el objetivo es claro:
<#list user.props() as prop>
${prop} = ${user.get(prop)}
</#list>
java
freemarker
tzador
fuente
fuente
${user[prop]}
como una abreviaturauser[prop]
funciona tanto comoprop
seaString
(de lo contrario, lo necesitauser?api.get(prop)
actualmente), pero tenga cuidado, algunos marcos (como Struts, creo) usan una configuración ahora obsoleta donde los nombres de los métodos se mezclan con lasMap
claves, y si el valor deprops
sucede sea un nombre de método en eluser
objeto Java, obtendrá el método en lugar de lo que quiso decir. Es también por eso que en esas configuraciones heredadas siempre usanuser.get(prop)
.FYI, parece que la sintaxis para recuperar los valores ha cambiado de acuerdo con:
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>
fuente
[key]
y.get(key)
existe desde la antigüedad..get(key)
no es especial para FTL, solo está llamando a ese método público de Java. Pero solo puede usarlo si FreeMarker se configuró para exponerMap
métodos.Desde 2.3.25, hazlo así:
Tenga en cuenta que esto también funciona con claves que no son cadenas (a diferencia de
map[key]
, que tenía que escribirse comomap?api.get(key)
entonces).Antes de 2.3.25, la solución estándar era:
Sin embargo, algunas integraciones de FreeMarker realmente antiguas usan una configuración extraña, donde los
Map
métodos públicos (comogetClass
) aparecen como claves. Eso sucede porque están usando un puroBeansWrapper
(en lugar deDefaultObjectWrapper
) cuyasimpleMapWrapper
propiedad se dejófalse
. Debe evitar esta configuración, ya que mezcla los métodos conMap
entradas reales . Pero si llegas a tener tal configuración desafortunado, la manera de escapar de la situación está usando los métodos de Java expuestas, tales comouser.entrySet()
,user.get(key)
, etc., y no usar las construcciones del lenguaje como plantilla?keys
ouser[key]
.fuente
${x?nosuchthing}
y pasa el cursor sobre él, el mensaje de error que se muestra le dirá qué versión de FreeMarker usa. Debería serlo2.3.25-incubating
.Si usa un BeansWrapper con un nivel de exposición de Expose.SAFE o Expose.ALL, entonces se puede emplear el enfoque estándar de Java para iterar el conjunto de entradas:
Por ejemplo, lo siguiente funcionará en Freemarker (desde al menos la versión 2.3.19):
<#list map.entrySet() as entry> <input type="hidden" name="${entry.key}" value="${entry.value}" /> </#list>
En Struts2, por ejemplo, se usa una extensión de BeanWrapper con el nivel de exposición predeterminado para permitir esta forma de iteración.
fuente
InvalidReferenceException
cuando lo probé, mientrasmap?keys
trabajaba.freemarker.ext.beans.BeansWrapper
como envoltorio de objetos. De lo contrario,Map
s se ajustará automáticamente a unSimpleHash
objeto que no admite#entrySet()
. (ver freemarker.sourceforge.net/docs/api/freemarker/template/… )BeansWrapper
, al menos no con sus valores predeterminados, dondesimpleMapWrapper
estáfalse
. Se vuelve muy confuso, ya que mezcla claves con nombres de métodos. Si necesita llamarentrySet()
, siga usando un contenedor de objetos "limpio", como el predeterminado, y escribamap?api.entrySet()
si necesita acceder a la API de Java en lugar de las claves.Objetos iterativos
Si sus claves de mapa son un objeto y no una cadena, puede iterarlas usando Freemarker.
1) Convierta el mapa en una lista en el controlador:
List<Map.Entry<myObjectKey, myObjectValue>> convertedMap = new ArrayList(originalMap.entrySet());
2) Itere el mapa en la plantilla Freemarker, accediendo al objeto en la Clave y al Objeto en el Valor:
fuente
Para completar, vale la pena mencionar que hay un manejo decente de colecciones vacías en Freemarker desde hace poco.
Entonces, la forma más conveniente de iterar un mapa es:
<#list tags> <ul class="posts"> <#items as tagName, tagCount> <li>{$tagName} (${tagCount})</li> </#items> </ul> <#else> <p>No tags found.</p> </#list>
No más
<#if ...>
envoltorios.fuente
Puede utilizar una comilla simple para acceder a la clave que estableció en su programa Java.
Si configura un mapa en Java como este
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);
Luego puede acceder a los miembros de 'hash' en Freemarker de esta manera:
${hash['firstname']} ${hash['lastname']}
Salida:
fuente