<#list> 中 Iterable 的 FreeMarker 错误
FreeMarker error with Iterable in <#list>
在 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)
...
怎么回事?
(如果其他人 运行 参与其中,我将通过问答来解决这个问题 - 我在这里没有找到它)
这里的问题是变量是 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
。
您需要打开 Iterable
支持。为了向后兼容,它默认关闭。您可能还应该升级 FreeMarker,因为至少在当前版本中,错误消息还包含以下内容:
Tip: The problematic value is a java.lang.Iterable. Using
DefaultObjectWrapper(..., iterableSupport=true) as the object_wrapper
setting of the FreeMarker configuration should solve this.
其中,当您使用 Java API 配置 FreeMarker 时,看起来像这样:
DefaultObjectWrapperBuilder owb = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_26);
owb.setIterableSupport(true);
cfg.setObjectWrapper(owb.build());
Spring
的示例
在控制器中
model.addAttribute("blogItems", blogItems);
return "main";
在模板中
<#list blogItems.iterator() as blogItem>
${blogItem.name}
</#list>
在 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)
...
怎么回事?
(如果其他人 运行 参与其中,我将通过问答来解决这个问题 - 我在这里没有找到它)
这里的问题是变量是 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
。
您需要打开 Iterable
支持。为了向后兼容,它默认关闭。您可能还应该升级 FreeMarker,因为至少在当前版本中,错误消息还包含以下内容:
Tip: The problematic value is a java.lang.Iterable. Using DefaultObjectWrapper(..., iterableSupport=true) as the object_wrapper setting of the FreeMarker configuration should solve this.
其中,当您使用 Java API 配置 FreeMarker 时,看起来像这样:
DefaultObjectWrapperBuilder owb = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_26);
owb.setIterableSupport(true);
cfg.setObjectWrapper(owb.build());
Spring
的示例在控制器中
model.addAttribute("blogItems", blogItems);
return "main";
在模板中
<#list blogItems.iterator() as blogItem>
${blogItem.name}
</#list>