将 java.lang.Iterable 视为 Freemarker 中的 #list 表达式
Posted
技术标签:
【中文标题】将 java.lang.Iterable 视为 Freemarker 中的 #list 表达式【英文标题】:Treat a java.lang.Iterable as a #list expression in Freemarker 【发布时间】:2011-09-05 16:03:55 【问题描述】:我有一个 java.lang.Iterable(实际上是一个 com.google.gson.JsonArray 实例)。
我想使用 freemarker (2.3.16) 枚举列表中的项目。
[#assign sports = controller.sports]
[#-- At this point, sports is bound to a com.google.gson.JsonArray instance. --]
[#list sports as sport]
$sport_index
[/#list]
我想避免仅仅为了有一个明确的项目集合而编写一个自定义 bean 和 Gson 反序列化器。使用 Gson(它已经为我将 JSON 字符串反序列化为 JsonObject)然后从该 JsonObject 创建我自己的对象 DAG 对我来说似乎很浪费。
不幸的是,我还没有找到让 Freemarker 将 java.lang.Iterable 视为列表的方法。我明白了:
freemarker.template.TemplateException : Expected collection or sequence.
controller.sports evaluated instead to freemarker.ext.beans.XMLStringModel on line 8, column 16 in sports.html.
freemarker.core.TemplateObject.invalidTypeException(line:135)
freemarker.core.IteratorBlock$Context.runLoop(line:190)
freemarker.core.Environment.visit(line:417)
freemarker.core.IteratorBlock.accept(line:102)
freemarker.core.Environment.visit(line:210)
【问题讨论】:
【参考方案1】:显式循环迭代器应该可以工作,例如:
[#list sports.iterator() as sport]
$sport_index
[/#list]
【讨论】:
我觉得自从这篇文章以来有一个更好的解决方案,我实际上使用它......但似乎无法找到它并弄清楚所以我再次使用它!谢谢!【参考方案2】:您所要做的就是将您的JsonArray
上的iterator()
的结果添加到上下文中。 Freemarker 足够聪明,可以从那里处理它,您可以像处理任何其他类似列表的变量一样在模板中引用它。
【讨论】:
【参考方案3】:Freemarker 现在通过以下方式创建您的 freemarker 配置来支持 Iterable
:
configuration = new Configuration(VERSION_2_3_28);
DefaultObjectWrapper objectWrapper = new DefaultObjectWrapper(VERSION_2_3_28);
objectWrapper.setIterableSupport(true);
configuration.setObjectWrapper(objectWrapper);
并更新到 2.3.28 版本(我不确定是哪个版本添加了这个,但 .23 没有它),然后只需实例化您的 Template
并传入该配置。
return new Template("somename", someReader, configuration);
【讨论】:
以上是关于将 java.lang.Iterable 视为 Freemarker 中的 #list 表达式的主要内容,如果未能解决你的问题,请参考以下文章
错误:只能遍历数组或 java.lang.Iterable 的实例
for-each不适用于表达式类型必需的数组或java.lang.iterable