ハッシュマップキーを反復処理するフリーマーカー


87

Freemarkerには、リストとハッシュマップの2つのコレクションデータ型があります。リストの場合と同じように、ハッシュマップキーを反復処理する方法はありますか?

したがって、データを含む変数がある場合は、次のように言います。

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 2013年

設定デフォルトではuser[prop]これまでのように作品propであるString(そうでない場合は、あなたが必要とするuser?api.get(prop)現在)、しかし、注意してください、いくつかのフレームワークは、(Strutsのように、私は信じている)メソッド名と混合されている現在は非推奨設定を使用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
この構文はどのように異なりますか?
パーカー

1
良い答え;-)値を出力するときにnullのチェックを行う必要がある場合があることに注意してください。<#if h [key] ??> $ {key} = $ {h [key]}; </#if>
ブラッドパークス

1
構文は変更されていません。どちら[key].get(key)古くから存在しています。.get(key)FTLにとって特別なことではなく、そのパブリックJavaメソッドを呼び出すだけです。ただし、FreeMarkerがMapメソッドを公​​開するように構成されている場合にのみ使用できます。
ddekany 2014

反復すると、メソッド(getClass、hashCode、equals、get、toString、class)を取得します...ただし、リストを取得したい 'id'のようなプロパティは表示されません。そのハッシュから非メソッドプロパティのリストを取得する方法について何か提案はありますか?それらのプロパティ名を知る必要があります。:|
MaxRocket 2017年

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)純粋なものを使用しているために発生simpleMapWrapperfalseます。メソッドと実際のMapエントリが混在するため、このような設定は避けてください。あなたは、このような不幸なセットアップに実行する場合でも、状況を脱出する方法は、次のような、公開Javaメソッドを使用しているuser.entrySet()user.get(key)のようなテンプレート言語の構文を使用してなど、ありません?keysuser[key]


これは完全に機能します。しかし、springsourceIDEでエラーが発生しています。それを修正する方法はありますか?ありがとう
harshavmb 2017

@harshavmbどのようなエラー?おそらく、古いFreeMarkerバージョンに付属している古いFreeMarkerプラグインを使用していますか?
ddekany 2017

そうは思わないでください。jbossツールから最新のものをダウンロードしました。他のマシンで試して、お知らせします。
harshavmb 2017

@harshavmbのようなものを入力してその上にカーソルを合わせる${x?nosuchthing}と、表示されるエラーメッセージに、使用しているFreeMarkerのバージョンが示されます。する必要があります2.3.25-incubating
ddekany 2017

奇妙なことに、私はMacで試したところ、問題を再現できませんでした。問題は私のvmだけにあるようです。jarバージョンを見てみましょう。ただし、これはエディターのエラーにすぎませんが、コードは正しく実行されました。
harshavmb 2017

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 2012年

4
これはfreemarker.ext.beans.BeansWrapper、オブジェクトラッパーとして使用する場合にのみ機能します。それ以外Mapの場合、sはをSimpleHashサポートしないオブジェクトに自動的にラップされます#entrySet()。(参照freemarker.sourceforge.net/docs/api/freemarker/template/...
Koraktor

あなたは正しいです、そして私はあなたのコメントを反映するために私の答えを更新しました。格好良い!
リース2012

1
BeanWrapperでSpringFreemarkerリゾルバーを使用している場合は特に、FTL内で作成されたハッシュに対して上記はうまく機能しません。Ftlファイル内で宣言されたハッシュはラップされず、?キーを使用して反復可能なハッシュになります。
スキップ

1
BeansWrapper少なくともデフォルトでsimpleMapWrapperは、純粋なを使用しないでくださいfalse。ここで、はです。キーとメソッド名が混在しているため、非常に混乱します。を呼び出す必要がある場合はentrySet()、デフォルトのような「クリーンな」オブジェクトラッパーを引き続き使用しmap?api.entrySet()、キーの代わりにJavaAPIにアクセスする必要がある場合は書き込みます。
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<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 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.