Рассматривайте java.lang.Iterable как выражение #list в Freemarker

У меня есть 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), чтобы затем создать мою собственную DAG объектов из этого JsonObject, кажется мне расточительным.

К сожалению, мне не удалось найти способ заставить 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)

person jabley    schedule 31.05.2011    source источник


Ответы (3)


Явный цикл по итератору должен работать, например:

[#list sports.iterator() as sport]
   ${sport_index}
[/#list]
person Chaquotay    schedule 31.05.2011
comment
Я чувствую, что после этого поста было лучшее решение, и я действительно использовал его ... но, похоже, не могу найти его и понять, поэтому я использую это снова! Спасибо! - person daniel9x; 03.06.2017

Все, что вам нужно сделать, это добавить результат iterator() к вашему JsonArray в контекст. Freemarker достаточно умен, чтобы обрабатывать его оттуда, и вы можете ссылаться на него в своем шаблоне, как на любую другую списочную переменную.

person stevevls    schedule 31.05.2011

Freemarker теперь поддерживает Iterable, создав конфигурацию freemarker через:

configuration = new Configuration(VERSION_2Template28);
DefaultObjectWrapper objectWrapper = new DefaultObjectWrapper(VERSION_2Template28);
objectWrapper.setIterableSupport(true);
configuration.setObjectWrapper(objectWrapper);

и обновление до версии 2.3.28 (я не совсем уверен, какая версия добавила это, но в .23 этого не было), а затем просто создайте экземпляр Template в этой конфигурации.

return new Template("somename", someReader, configuration);
person Mark Derricutt    schedule 24.07.2019