Freemarker ma dwa typy danych kolekcji, listy i hashmapy. Czy istnieje sposób na iterację po kluczach hashmap, tak jak robimy to z listami?
Więc jeśli mam zmienną z danymi, powiedzmy:
user : {
name : "user"
email : "[email protected]"
homepage : "http://nosuchpage.org"
}
Chciałbym wydrukować wszystkie właściwości użytkownika wraz z ich wartością. To jest nieprawidłowe, ale cel jest jasny:
<#list user.props() as prop>
${prop} = ${user.get(prop)}
</#list>
java
freemarker
tzador
źródło
źródło
${user[prop]}
skrótuuser[prop]
robót o ileprop
jestString
(poza tym, czego potrzebauser?api.get(prop)
obecnie), ale uwaga, niektóre ramy (jak Struts, wierzę) użyć teraz przestarzałej konfiguracji gdzie nazwy metod są zmieszane zMap
klawiszy, a więc wtedy, gdy wartośćprops
dzieje być nazwą metody wuser
obiekcie Java, otrzymasz metodę zamiast tego, co miałeś na myśli. Dlatego też w tych starszych konfiguracjach, których zawsze używająuser.get(prop)
.FYI, wygląda na to, że składnia pobierania wartości zmieniła się zgodnie z:
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>
źródło
[key]
i.get(key)
istnieje od czasów starożytnych..get(key)
nie jest specjalnie dla FTL, po prostu wywołuje tę publiczną metodę Java. Ale możesz go używać tylko wtedy, gdy FreeMarker został skonfigurowany do ujawnianiaMap
metod.Od 2.3.25 zrób to w ten sposób:
Zwróć uwagę, że działa to również z kluczami niebędącymi łańcuchami (w przeciwieństwie do tych
map[key]
, które musiały być zapisane tak jakmap?api.get(key)
wtedy).Przed 2.3.25 standardowym rozwiązaniem było:
Jednak niektóre naprawdę stare integracje FreeMarker używają dziwnej konfiguracji, w której
Map
metody publiczne (takie jakgetClass
) pojawiają się jako klucze. Dzieje się tak, ponieważ używają one czystegoBeansWrapper
(zamiastDefaultObjectWrapper
), któregosimpleMapWrapper
właściwość została pozostawionafalse
. Powinieneś unikać takiej konfiguracji, ponieważ łączy ona metody z prawdziwymiMap
wpisami. Ale jeśli napotkasz takim niefortunnym konfiguracji, tak aby uniknąć sytuacji korzysta odsłonięte metod Java, takich jakuser.entrySet()
,user.get(key)
itp, a nie przy użyciu konstrukcji językowych jak szablon?keys
lubuser[key]
.źródło
${x?nosuchthing}
i najedziesz na to kursorem, wyświetlony komunikat o błędzie powie, której wersji FreeMarker używa. Tak powinno być2.3.25-incubating
.Jeśli używasz BeansWrapper z poziomem ekspozycji Expose.SAFE lub Expose.ALL, możesz zastosować standardowe podejście Java do iteracji zestawu wpisów:
Na przykład następujące elementy będą działać w Freemarker (od wersji co najmniej 2.3.19):
<#list map.entrySet() as entry> <input type="hidden" name="${entry.key}" value="${entry.value}" /> </#list>
Na przykład w Struts2 używane jest rozszerzenie BeanWrapper z domyślnym poziomem ekspozycji, aby umożliwić ten sposób iteracji.
źródło
InvalidReferenceException
kiedy próbowałem, podczasmap?keys
pracy.freemarker.ext.beans.BeansWrapper
jako opakowanie obiektu. W przeciwnym razieMap
s zostanie automatycznie zawinięty wSimpleHash
obiekt, który nie obsługuje#entrySet()
. (patrz freemarker.sourceforge.net/docs/api/freemarker/template/... )BeansWrapper
, przynajmniej nie z jego domyślnymi ustawieniami, gdziesimpleMapWrapper
jestfalse
. Robi się to bardzo zagmatwane, ponieważ miesza klucze z nazwami metod. Jeśli chcesz zadzwonićentrySet()
, po prostu używaj „czystego” opakowania obiektu, takiego jak domyślny, i napisz,map?api.entrySet()
jeśli chcesz uzyskać dostęp do Java API zamiast kluczy.Iterowanie obiektów
Jeśli twoje klucze mapy są obiektem, a nie łańcuchem, możesz iterować za pomocą Freemarkera.
1) Konwertuj mapę na listę w kontrolerze:
List<Map.Entry<myObjectKey, myObjectValue>> convertedMap = new ArrayList(originalMap.entrySet());
2) Iteruj mapę w szablonie Freemarker, uzyskując dostęp do obiektu w kluczu i obiektu w wartości:
źródło
Dla kompletności warto wspomnieć, że od niedawna Freemarker przyzwoicie obsługuje puste kolekcje.
Najwygodniejszym sposobem iteracji mapy jest więc:
<#list tags> <ul class="posts"> <#items as tagName, tagCount> <li>{$tagName} (${tagCount})</li> </#items> </ul> <#else> <p>No tags found.</p> </#list>
Żadnych więcej
<#if ...>
opakowań.źródło
Możesz użyć pojedynczego cudzysłowu, aby uzyskać dostęp do klucza ustawionego w programie Java.
Jeśli ustawisz mapę w Javie w ten sposób
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);
Następnie możesz uzyskać dostęp do członków 'hash' w Freemarker w ten sposób -
${hash['firstname']} ${hash['lastname']}
Wynik :
źródło