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 comopropseaString(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 lasMapclaves, y si el valor depropssucede sea un nombre de método en eluserobjeto 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 exponerMapmé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
Mapmétodos públicos (comogetClass) aparecen como claves. Eso sucede porque están usando un puroBeansWrapper(en lugar deDefaultObjectWrapper) cuyasimpleMapWrapperpropiedad se dejófalse. Debe evitar esta configuración, ya que mezcla los métodos conMapentradas 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?keysouser[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
InvalidReferenceExceptioncuando lo probé, mientrasmap?keystrabajaba.freemarker.ext.beans.BeansWrappercomo envoltorio de objetos. De lo contrario,Maps se ajustará automáticamente a unSimpleHashobjeto que no admite#entrySet(). (ver freemarker.sourceforge.net/docs/api/freemarker/template/… )BeansWrapper, al menos no con sus valores predeterminados, dondesimpleMapWrapperestá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