使用Jackson以自定义顺序序列化对象属性

时间:2015-12-02 17:03:49

标签: java json jackson

我想知道是否可以使用Jackson的JsonSerializer生成JSON对象,其中属性按值排序(而非按键排序)。例如:

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

我尝试生成它,创建一个自定义的JsonSerializer,如下所示:

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();
    }
}

但是生成的JSON没有按属性值排序,杰克逊必须再次扰乱对象属性。有没有办法实现这个目标?

编辑:问题不在于Jackson,而是我用来检索JSON(CocoaRestClient)的应用程序,它改变了生成对象中属性的顺序。我的方法和@ m.aibin的方法都是正确的。 如果您遇到类似问题,请检查问题不是您用来检索JSON的应用程序。

2 个答案:

答案 0 :(得分:1)

您可以对地图进行排序,然后对其进行序列化。使用Jackson 2.3.1,您可以序列化SortedMap,例如LinkedHashMap,订单将得到尊重。

链接如何对哈希映射进行排序例如:Sorting HashMap by values

答案 1 :(得分:1)

我开发了Jersey 2 java服务,用于前端使用Angular 2/4,用于测试用过的Advanced Rest Client,用于数据序列化使用Jackson Java框架,在服务器端我用过LinkedHashMap<Integer, Object>,即Map,它保持了插入顺序,我使用自定义Jackson序列化程序序列化了该映射,原始字符串包含有序JSON map,但是在我使用{{1}之后使用该服务我看到,Advanced Rest Client取消了我的排序,即使原始响应已经排序,Advanced Rest Client也是如此。 这是因为我们违反Angular 2/4的规范,声称JSON或其他字Json object是无序集。 Json map中订购的内容为Json,因此我最终发送了Json array与已订购密钥的Json Map,因此我必须在{{1}上查看该数组方面是为了从Json Array重新创建订单。

<强> TL; DR

无需对Angular进行排序,您也不应该这样做,只需在Json Map中保持按键顺序。