I’ve got a `Map` and set it as model attribute in MVC Controller. Then I'd like to render this map in a loop in Freemarker view, e.g.
<#list myMap?keys?sort_by(“prop”) as key>
${key.prop} = ${myMap[key].fooProp}
</#list>
I have to loop through keys as they need to be displayed in a order. And surprisingly, it does NOT work!!!
After searching dozens of stack overflow as well as Freemarker docs, I've learnt that:
1. If the map's key type is not `String`, you cannot utilise the sugar syntax like `map[key]`, actually you can but it would return null value...
2. It seems there is some way to re-configure the Freemarker to enable syntax like `map?api.get(key)`, but it’s not trivial. I tried a few changes but did not work (see the TLDR below).
*TL;DR*
1. Need to set `api_builtin_enabled` to true, this can be done easily in our CustomFreemarkerConfiguration
2. After that it’s complaining "The value doesn't support ?api." and suggests to change another configuration on `object_wrapper` - Tip: In the FreeMarker configuration, `object_wrapper` is a `DefaultObjectWrapper` with its `useAdaptersForContainers` property set to false. Setting it to true might solves this problem.
3. Attempt to call `setUseAdaptersForContianers(true)` in the same class, and the startup of application failed, due to "Can't modify the freemarker.template.DefaultObjectWrapper object, as it was write protected."
4. Did not continue to hack freemarker config as the code now is related with some check across threads ...
Finally I decided to remodel my attribute into `Map` plus another `Map` to get around.
But still, who can think of any reason why FTL does not support the syntax for non-string-key-map?
评论