如何使用 JSON 以声明顺序使用枚举键序列化地图?

How to serialize a map with enum keys in declaration order with JSON?

我有一些枚举class,让我们想象一下

public enum MyEnum {
    ONE("one"), TWO("two"), THREE("three"), DEFAULT("some value")
    //..
}

和 Dto class:

@JsonPropertyOrder(value = {"id", "name", "params"})
public Dto {
    private Long id;
    private String name;
    private Map<MyEnum, Object> params;
}

如何在 params 映射中设置 keys 的顺序?我知道 LinkedHashMap 可用于设置顺序,只需按正确顺序添加到地图即可。但!在某些情况下,应该在运行时添加键值,并且应该将其添加到 params 映射而不是最后一个 link,而是在映射内部。例如

params = new LinkedHashMap();
params.put(ONE, new String("object1"));
params.put(THREE, new String("object #3"));

与我们刚刚添加的代码的另一个地方相比

params.put(TWO, new Integer(20));

json 中的顺序应该是:

{
 "id":"123", "name":"some name", 
"params":{"ONE":"object1","TWO":"20","THREE":"object #3"}
 }

我可以提出两个选项,它们都依赖于 Jackson 使用 MapSerializer 序列化 Map.

类型的对象这一事实

首先,由于 enum 类型根据它们的声明顺序定义隐式自然顺序,您可以启用 ObjectMapperSerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS。 javadoc 指出,

Feature that determines whether java.util.Map entries are first sorted by key before serialization or not: if enabled, additional sorting step is performed if necessary (not necessary for java.util.SortedMaps), if disabled, no additional sorting is needed.

换句话说,params 映射中的枚举将首先按声明顺序排序,然后才序列化。 请注意,此序列化功能适用于所有地图。

其次,您可以将 params 初始化为 EnumMap。要序列化 ​​MapMapSerializer 会迭代地图的 entrySet()EnumMap#entrySet()返回的entry set按照对应enum类型中常量的声明顺序排序。你会有

params = new EnumMap<>(MyEnum.class);
params.put(THREE, new String("object #3"));
params.put(ONE, new String("object1"));
// whatever order

Jackson 将按照声明枚举常量的顺序序列化它们。