简体   繁体   中英

How to retrive a List objects from HashMap and iterate in free marker template?

I have a Java Hashmap object which stores a key value pair in form of org.w3c.dom.Element : java.util.ArrayList . after populating the HashMap , I put it in Freemarker context along with List of org.w3c.dom.Element .

When I try to get the List object using below code snippet

<#list ElementList as key>
<#assign fh =ElemmentListMap>
  ${fh[key]}
</#list>

It says ${fh[key]} is undefined. Please let me how to get the solution for it or feel free to give another solution.

Update: Starting from 2.3.22, you should just use ?api to work this around. See this answer , or this FAQ entry for details.

The old answer:

The root of the problem here is that the FreeMarker Template Language doesn't have an equivalent of the Map type of Java. Instead it has a type called "hash", which is similar to a Map , but it only supports string keys (variable names, originally). So when it sees fh[key] , it will assume that key has a string value (in this case that will be the result of key.toString() due to how POJO-s are wrapped), and hence will not find the item. So the solution would be not using the [] operator for non-string keys, but the Java API, Map.get(Object key) .

And the rest is outdated...

But you will run into yet another obstacle if you try to do that: the default ObjectWrapper doesn't expose the methods of Map -s since the string keys of the Map already populate the same name-space. I hate the default ObjectWrapper for various other reasons too, so I always set up FreeMarker like this:

BeansWrapper wrapper = new BeansWrapper();
wrapper.setSimpleMapWrapper(true);
cfg.setObjectWrapper(wrapper);

With this wrapper you can use Map -s both as myMap[someStringKey] or as myMap(whateverKey) . So in your case it would be ${fh(key)} . Again, this doesn't work with the default ObjectWrapper .

To make things worse, I see you are using W3C DOM here. The above wrapper doesn't wrap Node -s automatically in a way so that you could use the FreeMarker XML features. So if you need that, then unless you always wrap DOM node manually, you will have to extend BeansWrapper to recognize DOM Node-s. That's simple to do luckily:

public class MyObjectWrapper extends freemarker.ext.beans.BeansWrapper {

    public TemplateModel wrap(Object obj) throws TemplateModelException {
        if (obj instanceof org.w3c.dom.Node) {
           return freemarker.ext.dom.NodeModel.wrap((org.w3c.dom.Node) obj);
        } else {
           return super.wrap(obj);
        }
    }

}

The last thing to consider if the environment you are using FreeMarker in already has a custom ObjectWrapper . In that case, you better try to extend that somehow...

Your java code should be:

Map map = new HashMap();
List list = new ArrayList();
list.add("red");
list.add("green");
list.add("blue");
map.put("array_list", list);

And the freemarker template should be:

<#list array_list as i>
    ${i}
</#list>

Output :

red
green
blue 

尝试像${fh.get(key)}一样引用它

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM