해시 맵 키를 반복하는 Freemarker


87

Freemarker에는 두 가지 컬렉션 데이터 유형, 목록 및 해시 맵이 있습니다. 목록과 마찬가지로 해시 맵 키를 반복하는 방법이 있습니까?

따라서 데이터가있는 var가 있으면 다음과 같이 말할 수 있습니다.

user : {
  name : "user"
  email : "looser@everything.com"
  homepage : "http://nosuchpage.org"
}

모든 사용자의 속성을 해당 값과 함께 인쇄하고 싶습니다. 이것은 유효하지 않지만 목표는 분명합니다.

<#list user.props() as prop>
  ${prop} = ${user.get(prop)}
</#list>

답변:


106

편집 : FreeMarker 2.3.25 이상에서는이 솔루션을 사용하지 마십시오 .get(prop). 특히 . 다른 답변을 참조하십시오.

내장 기능 을 사용 합니다. 예를 들어 다음과 같이 작동합니다.

<#list user?keys as prop>
    ${prop} = ${user.get(prop)}
</#list>  

4
내 답변에 게시 한 링크에 나와 있듯이 구문이 최신 버전에서 다릅니다. 나는 이것이 오래된 질문이라는 것을 알고 있지만 Google에서 높은 순위에 올랐습니다.
Nick Spacek 2011 년

26
참고-당신은 ${user[prop]}속기로 사용할 수 있습니다
Bozho

이것은 성능 누출입니다. 모든 키에 대해 값을 검색해야합니다. entrySet ()을 반복하면 그 문제가 없습니다.
Geoffrey De Smet 2013

4
$ {user [prop]}이어야합니다.
dns

구성 기본값으로 user[prop]작품까지 한 propA는 String(그렇지 않으면 당신이 필요로하는 user?api.get(prop)현재),하지만 조심 어떤 프레임 워크 (스트럿츠처럼, 내가 믿는) 메소드 이름이 혼합되어 지금은 사용되지 않는 설정 사용 Map키, 값이의 그렇게하면 props어떻게됩니까 userJava 객체 의 메서드 이름 이면 의미하는 대신 메서드를 얻습니다. 그렇기 때문에 레거시 설정에서 항상 user.get(prop).
ddekany 2015 년

52

참고로 값을 검색하는 구문이 다음에 따라 변경된 것 같습니다.

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>

2
이 구문은 어떻게 다른가요?
Parker

1
좋은 대답 ;-) 값을 인쇄 할 때 null을 확인해야 할 수도 있습니다. <#if h [key] ??> $ {key} = $ {h [key]}; </ # if>
Brad Parks

1
구문은 변경되지 않았습니다. 모두 [key].get(key)고대부터 존재한다. .get(key)FTL에 특별한 것이 아니라 공용 Java 메서드를 호출하는 것입니다. 그러나 FreeMarker가 Map메소드 를 노출하도록 구성된 경우에만 사용할 수 있습니다 .
ddekany 2014 년

반복 할 때 메서드 (getClass, hashCode, equals, get, toString, class)를 얻습니다.하지만 목록을 얻고 자하는 'id'와 같은 속성이 표시되지 않습니다. 해당 해시에서 비 메서드 속성 목록을 얻는 방법에 대한 제안이 있습니까? 그 속성 이름을 알아야합니다. : |
MaxRocket

47

2.3.25부터 다음과 같이하십시오.

<#list user as propName, propValue>
  ${propName} = ${propValue}
</#list>

이것은 문자열이 아닌 키에서도 작동한다는 점에 유의하십시오 ( 당시 map[key]로 작성되어야하는, 달리 map?api.get(key)).

2.3.25 이전의 표준 솔루션은 다음과 같습니다.

<#list user?keys as prop>
  ${prop} = ${user[prop]}
</#list>

그러나 일부 정말 오래된 FreeMarker 통합은 이상한 구성을 사용하는데, 공개 Map메서드 (예 getClass:)가 키로 나타납니다. 속성이 남아 있는 순수 BeansWrapper(대신 DefaultObjectWrapper)를 사용하기 때문에 발생 simpleMapWrapper합니다 false. 방법을 실제 Map항목 과 혼합하므로 이러한 설정은 피해야 합니다. 당신이 그런 불행한 설치로 실행한다면, 상황을 탈출 할 수있는 방법은 같은 노출 된 Java 메소드를 사용하고 user.entrySet(), user.get(key)같은 템플릿 언어 구조를 사용하는 등, 그리고 ?keysuser[key].


이것은 완벽하게 작동합니다. 그러나 springsource IDE에서 오류가 발생합니다. 그것을 고치는 방법을 아십니까? 감사합니다
harshavmb

@harshavmb 무슨 오류? 아마도 오래된 FreeMarker 버전과 함께 제공되는 오래된 FreeMarker 플러그인을 사용합니까?
ddekany

그렇게 생각하지 마십시오. jboss 도구에서 최신 버전을 다운로드했습니다. 다른 컴퓨터를 사용 해보고 알려 드리겠습니다.
harshavmb 15:53에

@harshavmb 같은 것을 입력하고 그 ${x?nosuchthing}위로 마우스를 가져 가면 표시되는 오류 메시지가 사용하는 FreeMarker 버전을 알려줍니다. 이어야합니다 2.3.25-incubating.
ddekany

이상하게도 Mac에서 시도했지만 문제를 복제 할 수 없습니다. 문제는 내 VM에만있는 것 같습니다. jar 버전을 살펴 보겠습니다. 하지만 에디터에서는 오류 일뿐 코드가 올바르게 실행되었습니다.
harshavmb

12

노출 수준이 Expose.SAFE 또는 Expose.ALL 인 BeansWrapper 를 사용하는 경우 항목 집합을 반복하는 표준 Java 접근 방식을 사용할 수 있습니다.

예를 들어, 다음은 Freemarker에서 작동합니다 (최소 버전 2.3.19부터).

<#list map.entrySet() as entry>  
  <input type="hidden" name="${entry.key}" value="${entry.value}" />
</#list>

예를 들어 Struts2 에서 BeanWrapper의 확장은 이러한 방식의 반복을 허용하도록 기본 노출 수준으로 사용됩니다.


3
실제로 시도해 보셨습니까? 일하는 InvalidReferenceException동안 시도했을 때 받았기 때문 map?keys입니다.
kdgregory

4
이것은 freemarker.ext.beans.BeansWrapper객체 래퍼로 사용할 때만 작동 합니다. 그렇지 않으면 Map는를 SimpleHash지원하지 않는 객체 로 자동으로 래핑됩니다 #entrySet(). (참조 freemarker.sourceforge.net/docs/api/freemarker/template/...를 )
Koraktor

귀하는 정확하며 귀하의 의견을 반영하기 위해 내 답변을 업데이트했습니다. 잘 봐!
리스

1
위의 내용은 특별히 BeanWrapper와 함께 Spring Freemarker 리졸버를 사용하는 경우 FTL 내부에서 생성 된 해시에 대해 잘 작동하지 않습니다. Ftl 파일 내에 선언 된 해시는 래핑되지 않으며? 키를 사용하여 해시 반복 가능합니다.
skipy

1
순수 사용하지 마십시오 BeansWrapper적어도 그 기본값으로, 어디는 simpleMapWrapper것입니다 false. 메서드 이름과 키를 혼합하기 때문에 매우 혼란스러워집니다. 를 호출해야하는 경우 entrySet()기본 래퍼와 같은 "깨끗한"개체 래퍼를 계속 사용 map?api.entrySet()하고 키 대신 Java API에 액세스해야하는 경우 작성 합니다.
ddekany 2015 년

2

반복 객체

맵 키가 문자열이 아니라 객체 인 경우 Freemarker를 사용하여 반복 할 수 있습니다.

1) 컨트롤러에서 맵을 목록으로 변환하십시오.

List<Map.Entry<myObjectKey, myObjectValue>> convertedMap  = new ArrayList(originalMap.entrySet());

2) Freemarker 템플릿에서 맵을 반복하여 키의 개체와 값의 개체에 액세스합니다.

<#list convertedMap as item>
    <#assign myObjectKey = item.getKey()/>
    <#assign myObjectValue = item.getValue()/>
    [...]
</#list>

1

완전성을 위해 최근부터 Freemarker에서 빈 컬렉션을 적절하게 처리하고 있음을 언급 할 가치가 있습니다.

따라서지도를 반복하는 가장 편리한 방법은 다음과 같습니다.

<#list tags>
<ul class="posts">
    <#items as tagName, tagCount>
        <li>{$tagName} (${tagCount})</li>
    </#items>
</ul>
<#else>
    <p>No tags found.</p>
</#list>

더 이상 <#if ...>래퍼가 없습니다 .


최고의 답변입니다. 감사합니다.
egemen

0

작은 따옴표를 사용하여 Java 프로그램에서 설정 한 키에 액세스 할 수 있습니다.

이와 같이 Java에서 Map을 설정하면

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);

그러면 다음과 같이 Freemarker에서 'hash'의 멤버에 액세스 할 수 있습니다.

${hash['firstname']}
${hash['lastname']}

출력 :

a
b

개별 키를 처리하는 방법을 보여 주지만 반복 방법을 묻는 질문
Lambart
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.