使用 Jackson 序列化带有排序键的 JSON

Posted

技术标签:

【中文标题】使用 Jackson 序列化带有排序键的 JSON【英文标题】:Serialized JSON with sorted keys, using Jackson 【发布时间】:2012-03-17 14:23:00 【问题描述】:

我正在尝试用 Jackson 替换 groovy/grails 项目中的自定义 JSON(反)序列化。

我无法让 Jackson 输出一个打印精美的 JSON,其中的键按简单的“自然”字母顺序排序。 我已经尝试过这个(以及许多变体):

mymap = [ ... ] // Some groovy map
def mapper = new ObjectMapper()
mapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true)
def jsonstring = mapper.defaultPrettyPrintingWriter().writeValueAsString(mymap)

但杰克逊顽固地生成了一个 JSON,其中的键似乎是随机顺序的。 我尝试使用 TreeMap 更改“mymap”的类型,在这种情况下,所有键都按预期正确排序。

我想知道是否有一种方法可以在不将上面的“mymap”更改为 TreeMap(并递归地更改其所有映射值...)的情况下对键进行排序。

SORT_PROPERTIES_ALPHABETICALLY 似乎正是为了做到这一点,但由于某种原因它没有这样做。 你知道这是为什么吗?上面有什么我做错了吗?

我尝试过使用 Jackson 1.8.3、1.8.8 和 1.9.5,结果相同(随机键)。

【问题讨论】:

【参考方案1】:

正如@tim_yates 所说,这不适用于地图键。

你可以使用

mapper.configure(SerializationConfig.Feature.ORDER_MAP_ENTRIES_BY_KEYS, true)

随着更新的版本 (>= 2.6.1) API 更改为:

mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);

【讨论】:

对我来说 JSON_MAPPER.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) 效果很好,这个答案很有帮助:) 很高兴听到! :-) 可以节省很多时间 ;-) 谢谢!在 v2.6.1 中,它似乎被移到了不同​​的包中。这对我有用:mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);【参考方案2】:

SORT_PROPERTIES_ALPHABETICALLY 的 documentation 明确表示:

定义用于 POJO 字段的默认属性序列化顺序的功能(注意:是否适用于地图序列化!)

所以我猜你需要改变你的输入地图(如你所说)

【讨论】:

好点,我错过了。看起来我可能不得不忘记设置序列化首选项的优雅方式。 你应该可以做到:def jsonstring = mapper.defaultPrettyPrintingWriter().writeValueAsString(mymap as TreeMap) 不能吗? 不,这没有帮助。 'mymap' 的实现不是 TreeMap。即使是这样,我也必须确保“mymap”中的所有其他地图值也是 TreeMap,这就是它变得非常棘手的地方。 确保查看下一个答案 - 您无需更改输入映射。 对我来说是writerWithDefaultPrettyPrinter() 打破了排序。没有漂亮的打印机 SORT_PROPERTIES_ALPHABETICALLY 完美工作【参考方案3】:

正如所指出的,此功能仅适用于 POJO。但是,我认为在Jackson Jira 处有对地图执行相同操作的功能请求;如果没有,这听起来像是一个很好的补充。

但与此同时,我会第二次 @tim_yates 建议使用中间 TreeMap 进行排序,并对其进行序列化: Map 的排序将按原样使用,所以这应该可行。

【讨论】:

以上是关于使用 Jackson 序列化带有排序键的 JSON的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Json.Net 序列化/反序列化带有自定义键的字典?

在 Swift 中编写一个带有排序键的漂亮打印 JSON 对象

jackson xml 列出了被识别为重复键的反序列化

可以将 Jackson 配置为反序列化 JSON 密钥(非值)吗?

使用 Jackson 序列化通用接口子类

在 Jackson / Spring Boot 中测试自定义 Json Deserializer