【问题标题】:Jackson Object mapper to convert java map to json maintaining order of keys杰克逊对象映射器将 java 映射转换为 json 维护键的顺序
【发布时间】:2014-02-17 09:01:37
【问题描述】:

我正在使用jackson.map.ObjectMapper API 将地图转换为 json 字符串。我正在使用 writeValueAsString 方法来实现这一点。

我将根据值排序的映射传递给writeValueAsString 方法。我得到的 JSON 字符串是基于键的。

有没有办法使用杰克逊将地图转换为 JSON 字符串,而不会干扰地图中项目的顺序。

我尝试将 Feature.SORT_PROPERTIES_ALPHABETICALLY 设置为 false,但根据文档,它仅适用于 POJO 类型。

实现上述行为的任何想法。

【问题讨论】:

  • 通用映射不能保证键的顺序,所以我不明白你怎么能做到这一点。
  • 您需要确保您使用的地图可以维护插入顺序,即 TreeMap 而不是 HashMap。
  • 我只使用了 Treemmap 并且值按我想要的方式排序。但是,一旦我将我的树图(实际上是一个包含所有树图的对象)传递给 Jackson API 以获取 JSON 字符串,我的所有地图值都会根据键进行处理。
  • 如果我错了,请纠正我,但我不知道有什么方法可以正确创建按与 java SortedMap 接口规范完全兼容的值排序的 Map。一对 SortedSet 就可以了。但是地图会出错。仅更新此类地图上的值就可以阻止一切。比较值的 Comparator 也违反了一些规则!请考虑使用 SortedSet of Pairs。

标签: java json jackson


【解决方案1】:

使用 Jackson 2.3.1(不知道以前的版本),您可以序列化 SortedMap,例如 TreeMap,将遵守顺序。

这是junit 4中的一个例子:

    @Test
public void testSerialize() throws JsonProcessingException{
    ObjectMapper om = new ObjectMapper();
    om.configure(SerializationFeature.WRITE_NULL_MAP_VALUES,false);
    om.configure(SerializationFeature.INDENT_OUTPUT,true);
    om.setSerializationInclusion(Include.NON_NULL);

    SortedMap<String,String> sortedMap = new TreeMap<String,String>();
    Map<String,String> map = new HashMap<String,String>();
    map.put("aaa","AAA");

    map.put("bbb","BBB");
    map.put("ccc","CCC");
    map.put("ddd","DDD");

    sortedMap.putAll(map);

    System.out.println(om.writeValueAsString(map));

    System.out.println(om.writeValueAsString(sortedMap));


}

结果如下:`

有地图

{
  "aaa" : "AAA",
  "ddd" : "DDD",
  "ccc" : "CCC",
  "bbb" : "BBB"
}

使用 SortedMap

{
  "aaa" : "AAA",
  "bbb" : "BBB",
  "ccc" : "CCC",
  "ddd" : "DDD"
}

`

第一个带有 Map 的序列化将不会被排序, 带有 TreeMap 的第二个将使用键按字母顺序排序。您可以将 Comparator 传递给 treeMap 以获得不同的顺序。

编辑:它也适用于带有 LinkedHashMap() 的 Jackson,即使这不是 SortedMap。这是 Map 的一个实现,它保持将键插入到映射中的顺序。这可能是您正在寻找的。​​p>

【讨论】:

  • 感谢您抽出宝贵时间。我尝试过使用树形图和链接哈希图。我正在将我的映射器配置为不使用以下配置属性对地图进行排序。 SORTED_MAPPER.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, false);当我将映射(树形图或链接的哈希图)传递给 writeValueAsString 方法时,这绝对可以正常工作,如下所示 SORTED_MAPPER.writeValueAsString(map);
  • 但是,我有 10 个不同的地图要转换为 JSON,因此我无法将地图对象传递给此方法。因此,我将所有地图放在一个对象中,并将该对象作为 SORTED_MAPPER.writeValueAsString(myObject) 传递给方法,其中 myObject 包含所有地图;由于某种原因,Jackson API 无法在这种情况下配置地图并根据键对所有地图进行处理。
  • Jackson 在某些边缘情况下有点问题,通常最好实现自己的序列化程序。 (baeldung.com/jackson-custom-serialization)。
  • @MartinKersten 是 Map 专用的自定义 Jackson 序列化器,是的。有那么一瞬间,我担心你提议在没有任何库的情况下进行所有 JSON 序列化。您是否有关于该边缘情况的更多信息,它是否涉及地图序列化?
  • 有几种情况,我支持的团队最终选择了自定义序列化器,或者当我在指挥时实现我们自己的 JSON 序列化机制。 JSON 相当简单,直接支持它很容易实现。我不喜欢注释和隐藏的魔法。序列化直接涉及数据,而数据是我们日常编程汤的主要成分。所以我喜欢一个能够序列化自身的数据对象,而不是“发现”如何序列化它。只要你有(模式)进化,事情就会变得混乱。所以定制几乎总是效果最好。团队通常认为这是一种解脱。
猜你喜欢
  • 1970-01-01
  • 2014-10-10
  • 2013-02-21
  • 2012-11-15
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多