如何使用Groovy优雅转换复杂嵌套数组型JSON结构?
JSON结构转换问题
接触Groovy几周,需要完成一个特定的JSON结构转换,原始JSON如下:
{ "collection_1": [ [ "value_1", "value_2", "value_3" ], [ "value_1", "value_2", "value_3", "value_4" ] ], "collection_2": [ [ "value_1", "value_2", "value_3", "value_4", "value_5" ] ], "collection_3": [ [ "value_1", "value_2" ] ] }
期望转换后的结构为:每个子列表中的字符串作为键,对应值统一设为false的Map,最终结构如下:
{ "collection_1": [ { "value_1": false, "value_2": false, "value_3": false }, { "value_1": false, "value_2": false, "value_3": false, "value_4": false } ], "collection_2": [ { "value_1": false, "value_2": false, "value_3": false, "value_4": false, "value_5": false } ], "collection_3": [ { "value_1": false, "value_2": false } ] }
自己尝试写了一段代码,但效果不好,想请教如何用Groovy的特性更优雅地完成转换:
Map<String, Object> getSelectableItems(Map<String, Object> jsonDeserialized) { def selectableItems = [:] jsonDeserialized.each { collection, subCollection -> selectableItems.put(collection, [:]) subCollection.eachWithIndex { items, index -> selectableItems.get(collection).putAt(index, items.collect { value -> [ "${value}" : false ] }) } } return selectableItems }
优雅实现方案
你的代码主要有两个问题:一是把每个子列表处理成了多个单键Map的列表,而不是一个包含所有键的Map;二是给selectableItems[collection]初始化时用了Map类型,实际应该用列表类型。
利用Groovy的集合操作特性,我们可以用更简洁的方式实现需求:
Map<String, List<Map<String, Boolean>>> getSelectableItems(Map<String, List<List<String>>> jsonDeserialized) { jsonDeserialized.collectEntries { collection, subCollections -> [collection, subCollections.collect { items -> items.collectEntries { [(it): false] } }] } }
代码说明:
collectEntries是Groovy专门用来将集合转换为Map的便捷方法,直接返回由键值对组成的Map- 外层
collectEntries遍历原始Map的每个键值对,生成新的键值对:键保留原集合名,值是处理后的子列表 - 内层
collect遍历每个子列表,再通过collectEntries把列表里的每个字符串转换为Map的键,对应值固定为false
这个实现完全借助Groovy的闭包和集合操作特性,代码更简洁、可读性更高,完美匹配你的转换需求。
内容的提问来源于stack exchange,提问作者Anthony Meinder
相关产品推荐
相关产品推荐

