Treat java.lang.Iterable as #list expression in Freemarker

I have java.lang.Iterable (in fact, an instance of com.google.gson.JsonArray).

I would like to list the items in a list using 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] 

I would like to avoid having to write a custom bean and Gson handle to have an explicit set of elements. Using Gson (which already deserializes the JSON string for JsonObject for me) to then create my own DAG of objects from this JsonObject seems to me wasteful.

Unfortunately, I could not find a way to get Freemarker to treat java.lang.Iterable as a list. I get:

 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) 
+4
source share
3 answers

Explicit loop execution on an iterator should work, for example:

 [#list sports.iterator() as sport] ${sport_index} [/#list] 
+5
source

All you have to do is add the result of iterator() to your JsonArray to the context. Freemarker is smart enough to process it from there, and you can reference it in your template, as well as any other variable like a list.

+1
source

Freemarker now supports Iterable by creating a Freemarker configuration through:

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

and upgrade to release 2.3.28 (I'm not quite sure which version added this, but .23 didn't have it), and then just create an instance of your Template passed in this configuration.

 return new Template("somename", someReader, configuration); 
0
source

All Articles