Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Passing map <Integer, String> to Soy renders in wrong order

Svante Gustafsson Björkegren
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 24, 2014

I am creating a Stash plugin using Soy to render a configuration UI. The servlet is calling the render-function with a LinkedHashMap which is populated in the JAVA code correctly. (printouts showing the correct order of elements)

render(resp, template, ImmutableMap.&lt;String, Object&gt;of("project", project, "data", data));

Example printout of data in JAVA function:

{1=[rep_1, rep_1], 11=[rep_2, rep_2], 12=[rep_3, rep_3], 21=[rep_4, rep_4]}

But when the render function has created the UI page from the Soy template the order of the elements in the passed HashMap is all wrong. I am doing a

{foreach $key in keys($data)}
	{$key} : {$data[$key]}&lt;br&gt;
{/foreach}

and the elements are printed in some random order.

The order (as printed on the rendered UI page:

21 : [rep_4, rep_4]
1 : [rep_1, rep_1]
11 : [rep_2, rep_2]
12 : [rep_3, rep_3]

 

Isn't it possible to control the order the elements are accessed in the map in the Soy template?

Cheers,

// Svante

3 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

2 votes
Answer accepted
jhinch _Atlassian_
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
November 25, 2014

Soy does not preserve the implementation of Maps it is provided. So even if you are using a `LinkedHashMap` or an `ImmutableMap` which have a stable iteration order, soy is not guaranteed to preserve the underlying implementations order.

If you want to have a collection or ordered things you are better to use a `List` instead. All `Iterable`s are converted to `List`s in soy so you can rely on their ordering. 

Svante Gustafsson December 4, 2014

Yep, this did the trick! I passed on an ArrayList of ArrayLists and now my order is correct, thnx! It is a bit more tricky to "unpack" this on the Soy side but it works with some clever logic!

0 votes
Mathias Edblom November 25, 2014

I would think a little bit different and not sorting the Map, and instead sort the keys and send them to the Soy template as well.

You can do this with

SortedSet&lt;Integer&gt; keys = new TreeSet&lt;Integer&gt;(map.keySet());

Send the keys to the Soy template and render the Soy template like this:

{foreach $key in $keys}
	{$key} : {$map[$key]} : {index($key)}&lt;br&gt;
{/foreach}

Cheers //M

0 votes
Marcin
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
November 24, 2014

What you want is a SortedMap - a HashMap doesn't guarantee order of the keys.  Guava has an ImmutableSortedMap class you can use to create these. By default a SortedMap will sort the keys in their "natural order", which is what you want in this case if you want them in integer order.

TAGS
AUG Leaders

Atlassian Community Events