Java 在hashmap键上迭代的Freemarker

Java 在hashmap键上迭代的Freemarker,java,freemarker,Java,Freemarker,Freemarker有两种集合数据类型:列表和哈希映射 有没有一种方法可以像处理列表一样迭代hashmap键 因此,如果我有一个带有数据的var,让我们说: user : { name : "user" email : "looser@everything.com" homepage : "http://nosuchpage.org" } 我想打印所有用户的属性及其值。 这是无效的,但目标很明确: <#list user.props() as prop> ${pro

Freemarker有两种集合数据类型:列表和哈希映射 有没有一种方法可以像处理列表一样迭代hashmap键

因此,如果我有一个带有数据的var,让我们说:

user : {
  name : "user"
  email : "looser@everything.com"
  homepage : "http://nosuchpage.org"
}
我想打印所有用户的属性及其值。 这是无效的,但目标很明确:

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

${prop}=${user.get(prop)}

编辑:不要将此解决方案用于FreeMarker 2.3.25及以上版本,尤其是
.get(prop)
。请参阅其他答案

您可以使用内置功能,例如,这应该可以:

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

${prop}=${user.get(prop)}

仅供参考,检索值的语法似乎已根据以下情况更改:


${key}=${h[key]};
如果使用暴露级别为Expose.SAFE或Expose.ALL的,则可以使用迭代条目集的标准Java方法:

例如,以下内容将在Freemarker中使用(因为至少版本2.3.19):



例如,在Struts2中,与默认的公开级别一起使用,以允许这种迭代方式。

您可以使用一个引号来访问您在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);
输出:

a
b
迭代对象 如果贴图关键帧是对象而不是字符串,则可以使用Freemarker对其进行迭代

1) 将地图转换为控制器中的列表:

List<Map.Entry<myObjectKey, myObjectValue>> convertedMap  = new ArrayList(originalMap.entrySet());
List convertedMap=new ArrayList(originalMap.entrySet());
2) 在Freemarker模板中迭代贴图,访问键中的对象和值中的对象:

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

[...]

从2.3.25开始,按如下方式操作:

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

然而,一些非常古老的FreeMarker集成使用了一种奇怪的配置,其中公共
Map
方法(如
getClass
)显示为键。这发生在他们使用纯
BeansWrapper
(而不是
DefaultObjectWrapper
)时,其
simpleMapWrapper
属性保留在
false
上。您应该避免这样的设置,因为它将方法与real
Map
条目混合在一起。但是,如果您遇到这种不幸的设置,摆脱这种情况的方法是使用公开的Java方法,例如
user.entrySet()
user.get(key)
,等等,为了完整性,不要使用模板语言构造,如
?keys
user[key]
,值得一提的是,自最近以来,Freemarker对空集合的处理相当不错

因此,迭代贴图最方便的方法是:

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

  • {$tagName}(${tagCount})
没有找到标签



不再使用
包装器。

最新版本的语法不同,如我在回答中发布的链接所示。我意识到这是一个老问题,但它在Google上排名很高。只需注意-您可以使用
${user[prop]}
作为缩写这是一个性能泄漏:对于每个键,它都需要检索值。迭代entrySet()没有这个问题。应该是${user[prop]},配置默认值为
user[prop]
,只要
prop
String
(否则当前需要
user?api.get(prop)
),但是要注意,有些框架(我相信是Struts)是这样的)使用现在不推荐使用的设置,其中方法名与
Map
键混合,因此如果
props
的值恰好是
user
Java对象中的方法名,那么您将得到方法而不是您想要的。这也是为什么在那些传统设置中,他们总是使用
user.get(prop)
。这种语法有什么不同?回答得好;-)请注意,在打印值${key}=${h[key]}时,可能需要检查是否为null;语法没有改变。
[key]
.get(key)
自古以来就存在
.get(key)
对FTL没有任何特殊性,它只是调用公共Java方法。但您只能在FreeMarker配置为公开
Map
方法时使用它。迭代时,我获取方法(getClass、hashCode、equals、get、toString、class)。。。然而,我没有看到任何像“id”这样的属性,这是我想要得到的列表。对于如何从该散列中获取非方法属性列表,有什么建议吗?我需要知道那些财产的名称|你真的试过这个吗?因为我在尝试时得到了一个
InvalidReferenceException
,而
map?键
起作用。这只在使用
freemarker.ext.beans.BeansWrapper
作为对象包装时起作用。否则,
Map
s将自动包装到不支持
#entrySet()
SimpleHash
对象中。(见)你是对的,我更新了我的答案以反映你的评论。很好看!对于FTL内部创建的散列,上述方法无法很好地工作,特别是如果您将Spring Freemarker解析器与BeanRapper一起使用。Ftl文件中声明的哈希没有包装,仍然只是使用?键的哈希表。不要使用纯
BeansWrapper
,至少不要使用其默认值,其中
simpleMapWrapper
false
。它变得非常混乱,因为它混合了键和方法名。如果您需要调用
entrySet()
,只需继续使用“干净”的对象包装器,就像默认的那样,如果您需要访问Java api而不是键,请编写
map?api.entrySet()
。这非常有效。但是,我在SpringSourceIDE中看到了错误。你知道怎么修吗?Thanks@harshavmb什么错误?它是否使用了一个过时的FreeMarker插件,可能是一个旧的FreeMarker版本?我不这么认为。已从jboss工具下载了最新版本。我将在另一台机器上试用,并让您知道。@harshavmb如果您输入类似于
${x?nosuchthing}
的内容并将鼠标悬停在上面,则会显示错误消息
<#list convertedMap as item>
    <#assign myObjectKey = item.getKey()/>
    <#assign myObjectValue = item.getValue()/>
    [...]
</#list>
<#list user as propName, propValue>
  ${propName} = ${propValue}
</#list>
<#list user?keys as prop>
  ${prop} = ${user[prop]}
</#list>
<#list tags>
<ul class="posts">
    <#items as tagName, tagCount>
        <li>{$tagName} (${tagCount})</li>
    </#items>
</ul>
<#else>
    <p>No tags found.</p>
</#list>