Menu

#89 Map iteration doesn't work if the key is a Class instance

2.4.1+
open-accepted
nobody
None
9
2015-08-26
2013-04-15
No

The values are always null, because ${map[key]) will first toString() the Class instance.

Also, Map entry set iteration is a big pita (and a small performance leak):
http://colinyates.blogspot.be/2009/05/freemarker-iterating-map.html

Discussion

  • Dániel Dékány

    Simply put, FTL doesn't know non-string keys. This is not really a bug in that this is a historical design limitation (yeah, that's a polite word for that...) which is "well known"/documented. Fixing this is difficult, especially as backward-compatibility is important at this point. Same kind of problem with entrySet. (I actually plan to fix this in the summer, together with a lot of other historical baggage.) (To work this around right now, you could use pure BeansWrapper with setSimpleMaps set to true, and then you can do map(key) instead of map[key].)

     
  • Geoffrey De Smet

    Thanks for replying.

    I don't think this historical design limitation isn't well known/documented: I came across the problem, google about the problem (not the solution because I don't know that) for hours with no result. It's very unintuitive that "map[myClass]" calls "map.get(myClass.toString())" when "map instanceof Map<MyClass, Value>" and always returns null.

    So bascially, Java with FTL does this code:
    // In Java when populating the data
    Map<Color, String> map = new HashMap<Color, String>();
    map.put(Color.RED, "beautifull");
    // In FTL when rendering the data
    String value = map.get(Color.RED.toString()); // RETURNS NULL

    Who would want to return null there?
    By not returning null, I don't think you're breaking backwards compatbility: I think you're fixing a bug :)

     
  • Geoffrey De Smet

    • priority: 5 --> 9
     
  • Dániel Dékány

    By fixing this, and making the intuitive one the default behavior, I would break many existing templates, and that's of course unacceptable.

    As of this being not well documented, it's in the FAQ. And if someone looks at the API (OK, that's not common), it turns out that TemplateHashModel.get wants a String parameter... so you just can't pass anything else to it. That's basically the historical reason, and also why changing it upsets the code base pretty much. TemplateHashModel was for sub-variables originally, that had a name.

     
  • Dániel Dékány

    TemplateMapModel will have to be added (while TemplateHashModel-s reamin for B.C.) to put an end to the non-string-keys issues, and there entry listing will have to be a function of this model.

    Meanwhile, ?api allows using the Java API-s of wrapped Map-s.

     
  • Dániel Dékány

    • status: open --> open-accepted
    • Group: --> undecided
     
  • Dániel Dékány

    • Group: undecided --> 2.4.1+
     

Log in to post a comment.