Freemarker: How to iterate through the Map using enums as keys

前端 未结 2 524
心在旅途
心在旅途 2020-12-06 01:28

The following code does not work because Freemarker seems to cast the value of the expression inside [] to String and then to use it as a key, which is not what is actually

相关标签:
2条回答
  • 2020-12-06 02:23

    The accepted answer isn't the simplest solution since 2.3.22. While myMap[key] still assumes a string key (see FAQ entry why), now one can use myMap?api.get(key) as a workaround. It needs some configuring though:

    • First of all, ?api is disallowed by default, so you need to set the api_builtin_enabled (Configuration.setAPIBuiltinEnabled(boolean)) setting to true.
    • Then, the object_wrapper (Configuration.setObjectWrapper(ObjectWrapper)) used needs to support this feature (exposing the API). If you don't set the object_wrapper anywhere, then just increasing the incompatible_improvements setting (the Configuration constructor parameter, or Configuration.setIncompatibleImprovements(Version)) to 2.3.22 solves this. If you set the object_wrapper (i.e., you overwrite the default), and it's a DefaultObjectWrapper instance, then note that DefaultObjectWrapper has its own incompatibleImprovements property that has to be set to 2.3.22. If you are using pure BeansWrapper (not recommended!) then you have to do nothing, as it always supports this feature.
    0 讨论(0)
  • 2020-12-06 02:27

    To paraphrase Freemarker Documentation FAQ on this,

    You can't use non-string keys in the myMap[key] expression. You can use methods!

    So, you could create a bean that provides a way for you to get to your Java EnumMap, (i.e). Then just instantiate this bean with your mapp, and put the bean in your Model.

    class EnumMap
    {
        HashMap<MyEnum, String> map = new HashMap<MyEnum, String>();
    
        public String getValue(MyEnum e)
        {
            return map.get(e);
        }    
        ..constructor, generics, getters, setters left out.
    }
    

    I'm a little bit confused about what general goal your trying to accomplish. If you just need to list out the values of the enum (or perhaps a display value for each one). There is a much easier way to do it.

    One way I've seen this problem solved is by putting a display value on the Enum instances.

    i.e

    enum MyEnum 
    {   FOO("Foo"), 
        BAR_EXAMPLE("Bar Example"); 
        private String displayValue;
    
        MyEnum(String displayValue)
        {
            this.displayValue = displayValue;
        }
    
        public String getDisplay()
        {
            return displayValue;
        }
    }
    

    This allows you to put the Enum itself into your configuration, and iterate over all instances.

    SimpleHash globalModel = new SimpleHash();
    TemplateHashModel enumModels = BeansWrapper.getDefaultInstance().getEnumModels();
    TemplateHashModel myEnumModel = (TemplateHashModel) enumModels.get("your.fully.qualified.enum.MyEnum");
    
    globalModel.put("MyEnum", myEnumModel);
    freemarkerConfiguration.setAllSharedVariables(globalModel);
    

    Then you can iterate over the enum,

    <#list MyEnum?values as item>
        ${item.display}
    </#list> 
    
    0 讨论(0)
提交回复
热议问题