有一个对象映射器功能来序列化按地图键排序的地图,但没有任何关于java集的说法。如果我将项目存储在我的POJO中的java.util.Set中,那么Jackson ObjectMapper会以任何顺序将它们序列化为json数组吗?
如果没有,我正在考虑为此目的为该集编写自定义序列化程序 - 是否有更好的方法可以建议?
更新
最终,目标是在一个"请求中将一组唯一整数反序列化为某种容器。 POJO。然后处理请求并将该输入字段传递到"响应"中的相应输出字段(未更改)。对象
我希望将数据存储在POJO中作为java.util.Set,以保证所有用户满意(如果您尝试将其存储为Set的子类型,那么POJO的消费者接口可能会因为他们不能获得一个Set而不得不期待一个HashSet或TreeSet而感到沮丧。
这会有用吗?
上面的第3项是我想知道的 - ObjectMapper会使用POJO字段的运行时类型,还是声明的类型?
答案 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
。