Jackson ObjectMapper:java.util.Set是按升序排序顺序为json数组吗?

时间:2017-11-06 19:31:34

标签: java json serialization jackson set

有一个对象映射器功能来序列化按地图键排序的地图,但没有任何关于java集的说法。如果我将项目存储在我的POJO中的java.util.Set中,那么Jackson ObjectMapper会以任何顺序将它们序列化为json数组吗?

如果没有,我正在考虑为此目的为该集编写自定义序列化程序 - 是否有更好的方法可以建议?

更新

最终,目标是在一个"请求中将一组唯一整数反序列化为某种容器。 POJO。然后处理请求并将该输入字段传递到"响应"中的相应输出字段(未更改)。对象

我希望将数据存储在POJO中作为java.util.Set,以保证所有用户满意(如果您尝试将其存储为Set的子类型,那么POJO的消费者接口可能会因为他们不能获得一个Set而不得不期待一个HashSet或TreeSet而感到沮丧。

这会有用吗?

  1. json数组[5,4,3,2,1]被反序列化为Set BUT,我在setter方法上使用@JsonDeserialize(as = TreeSet.class)。因此,对象的运行时类型现在是TreeSet(即使它作为Set存储在POJO中)。
  2. Set通过服务器传递,最终结束存储在响应POJO中(即使POJO字段类型为Set,运行时类型仍为TreeSet)。
  3. ObjectMapper将TreeSet序列化为json数组[1,2,3,4,5](因为TreeSet是自然排序的)。
  4. 上面的第3项是我想知道的 - ObjectMapper会使用POJO字段的运行时类型,还是声明的类型?

2 个答案:

答案 0 :(得分:1)

JSON数组是有序集合,与Java数组完全相同:

  

数组有序值的集合。数组以[(左括号)开头,以](右括号)结尾。值以,(逗号)分隔。

但是,有序并不意味着已排序。它只是意味着它保留了给定值的 order

  • 如果Set已排序(例如TreeSet),则根据Set的排序顺序,JSON数组已排序

      

    TreeSet:元素按照自然顺序排序,或者按照创建时间提供的Comparator排序,具体取决于使用的构造函数。

  • 如果Set无序(例如HashSet),则JSON数组采用Set返回的任意顺序。< / p>

      

    HashSet:它不能保证集合的迭代顺序;特别是,它不保证订单会随着时间的推移保持不变。

这与JSON对象的字段不同:

  

对象是一组无序名称/值对。对象以{(左大括号)开头,以}(右大括号)结束。每个名称后跟:(冒号),名称/值对由,(逗号)分隔。

答案 1 :(得分:0)

可以创建 Jackson Converter 来对 Set 进行排序,将其转换为具有所需排序顺序的元素的 LinkedHashSet

public class OrderedSetConverter 
        extends StdConverter<Set<Integer>, Set< Integer >> {
    @Override
    public Set<DayOfWeek> convert(Set<Integer> value) {
        return value == null ? null : value.stream()
                .sorted(Comparator.nullsLast(Comparator.naturalOrder()))
                .collect(Collectors.toCollection(LinkedHashSet::new));
    }
}

public class MyType {
    @JsonSerialize(converter = OrderedSetConverter.class)
    private Set<Integer> myValues;
}

当使用 JsonSerialize 应用于属性时,生成的 JSON 数组将按排序顺序排列。此外,这可以应用到使用 JsonDeserialize 的属性,确保读取 JSON 产生的对象将具有 LinkedHashSet 和排序的迭代顺序。


出于几个原因,我在我的项目中使用了这种方法,而不是使用 TreeSet。首先,我想接受集合中的 null 值(主要是这样我可以使用我的标准空值处理来处理它们并带有适当的 API 错误消息,而不是在创建时出现 NullPointerException TreeSet。其次,TreeSet 改变了标准集合契约中集合的语义,使用 Comparable 对象的 compareTo 方法来确定两个对象是否相等,而不是Objevt.equals()。最后,我希望 Java API 的客户能够使用对其应用程序有意义的任何有效 Set 类型,而不是仅限于 TreeSet