<#list> 中的 Iterable 出现 FreeMarker 错误
Posted
技术标签:
【中文标题】<#list> 中的 Iterable 出现 FreeMarker 错误【英文标题】:FreeMarker error with Iterable in <#list> 【发布时间】:2018-03-04 16:59:58 【问题描述】:在 FreeMarker 模板中,我将一个变量传递给 <#list>
:
<#list sectorTags as sector>
<td colspan="$sector.designatedTags!?size">$sector.name</td>
<#else>
<td>No technology sectors defined.</td>
</#list>
但是失败了:
06:25:03,733 SEVERE freemarker.core.NonSequenceOrCollectionException: Expected a sequence or collection, but this has evaluated to an extended_hash+string (com.tinkerpop.frames.structures.FramedVertexIterable wrapped into f.e.b.StringModel):
==> sectorTags [in template "reports/templates/techReport-punchCard.ftl" at line 105, column 32]
----
FTL stack trace ("~" means nesting-related):
- Failed at: #list-#else-container [in template "reports/templates/techReport-punchCard.ftl" at line 105, column 25]
----
at freemarker.core.IteratorBlock$IterationContext.executeNestedBlockInner(IteratorBlock.java:295)
...
发生了什么事?
(如果其他人遇到这个问题,我会通过问答来解决这个问题 - 我在这里没有找到)
【问题讨论】:
【参考方案1】:这里的问题是变量是Iterable
。 FreeMarker 目前无法处理该问题(即将Iterable
转换为Iterator
或Collection
)。
Iterable
必须明确转换为 Iterator
:
<#list sectorTags.iterator() as sector>
<td colspan="$sector.designatedTags!.iterator()?size">$sector.name</td>
<#else>
<td>No technology sectors defined.</td>
</#list>
Iteratable
没有被自动隐藏的原因在 Jira 问题(我现在找不到)中进行了讨论。如果我没记错的话,那是因为Java中有一些类型是Iterable
,但不希望自动将它们变成Iterators
。
【讨论】:
为了以后的读者,FreeMarker确实支持直接列出Iterable
-s(无需转换)。这是一个配置问题;有关更多信息,请参阅我的答案。【参考方案2】:
您需要开启Iterable
支持。为了向后兼容,默认情况下它是关闭的。您可能还应该升级 FreeMarker,因为至少在当前版本中,错误消息还包含以下内容:
提示:有问题的值是 java.lang.Iterable。使用 DefaultObjectWrapper(..., iterableSupport=true) 作为 object_wrapper FreeMarker 配置的设置应该可以解决这个问题。
其中,当您使用 Java API 配置 FreeMarker 时,看起来像这样:
DefaultObjectWrapperBuilder owb = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_26);
owb.setIterableSupport(true);
cfg.setObjectWrapper(owb.build());
【讨论】:
供参考,这里是Iterable support PR【参考方案3】:Spring 示例
在控制器中
model.addAttribute("blogItems", blogItems);
return "main";
在模板中
<#list blogItems.iterator() as blogItem>
$blogItem.name
</#list>
【讨论】:
以上是关于<#list> 中的 Iterable 出现 FreeMarker 错误的主要内容,如果未能解决你的问题,请参考以下文章
“Iterable<Element> 不能转换为 List<Element>” - `List` 不是 `Iterable` 的一种吗?
参数类型“List<Categories>”不能分配给参数类型“Iterable<Categories>”