使用 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 对象