4

I would like to know if it is possible to generate a JSON object with Jackson's JsonSerializer where the properties are ordered by value (not by key). For example:

{
    "property2": 320,
    "property1": 287,
    "property4": 280,
    "property3": 123,
    ...
}

I tried to generate it creating a custom JsonSerializer like this:

public class MySerializer extends JsonSerializer<Map<String, Long>> {

    @Override
    public void serialize(Map<String, Long> t, JsonGenerator jg, SerializerProvider sp) throws IOException, JsonProcessingException {
        List<Entry<String, Long>> list = new ArrayList<>(t.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, Long>> () {
            @Override
            public int compare(Map.Entry<String, Long> o1, Map.Entry<String, Long> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });
        jg.writeStartObject();
        for(Entry<String, Long> entry : list) {
            jg.writeNumberField(entry.getKey(), entry.getValue());
        }
        jg.writeEndObject();
    }
}

But the JSON generated is not sorted by property value, Jackson must be disordering again the object properties. Is there any way to achieve this?


EDIT: The problem was not with Jackson, but with the application I used to retrieve the JSON (CocoaRestClient), which changes the order of the properties in the generated object. Both my approach and @m.aibin's one are correct. If you have a similar problem, please check that the problem is not the application you are using to retrieve the JSON.

jeojavi
  • 876
  • 1
  • 6
  • 15

2 Answers2

1

You can sort your map and then serialize it. With Jackson 2.3.1 you can serialize a SortedMap, for example a LinkedHashMap, the order will be respected.

Link how to sort a hash map is for example here: Sorting HashMap by values

Community
  • 1
  • 1
m.aibin
  • 3,528
  • 4
  • 28
  • 47
  • Thanks for you answer m.aibin. I created a SortedMap and then serialized it but the result is still not ordered, neither by value nor by key. Jackson might be ignoring this order. – jeojavi Dec 02 '15 at 17:45
  • @Javi Fernandez but did you sort this map? It's not sorted by default, this is an implementation of Map that keep the order which keys were inserted into the map, you need to sort and return a new sorted map, then serialize it – m.aibin Dec 02 '15 at 17:49
  • Yes, I sorted the Map. I tried several approaches: creating a `SortedMap`, creating a `LinkedHashMap` (with the code in the answer you linked), and even creating a `List` (as described in the question), but none of them worked. The properties are sorted in the object, but not in the `JSON`, so I think Jackson might be disordering it. – jeojavi Dec 02 '15 at 18:23
1

I developed Jersey 2 java services, for front-end used Angular 2/4, for testing used Advanced Rest Client, for data serialization used Jackson Java framework and on server side I had LinkedHashMap<Integer, Object>, which is Map, that keeps insertion order, I serialized that map using custom Jackson serializer, the raw string contained ordered JSON map, however after I consumed that service Using Advanced Rest Client I saw, that Advanced Rest Client canceled my sorting, even though raw response was sorted and the same goes for Angular 2/4. That's because we are going against the specification of JSON, which claims that Json object or in other words Json map is unordered set. What is ordered in Json is Json array, so I ended up sending Json Map coupled with Json Array which had ordered keys, so I had to look at that Array on Angular side in order to recreate order from the Json Map.


TL;DR

There is no need to sort Json Map and you shoud not do that, just keep keys order in Json Array.

Benas
  • 2,106
  • 2
  • 39
  • 66