json - 如何在 Groovy 中展平和拆分这个 JSON?
问题描述
我可以使用一些帮助来编写 Groovy 脚本,以基于嵌套数组元素将 JSON 展平和拆分为多个 JSON-s。这是原始的 JSON:
{
"input_query": {
"discount_guid": "3afeb169-7969-4f6f-8928-d801692848b1",
"user_uid": 5467890,
"shopping_list": [
{
"article_id": 311729,
"current_price_without_promo": 7.69,
"promo_discount": 0,
"count": 1,
"apply_discount": true
},
{
"article_id": 229752,
"current_price_without_promo": 11.29,
"promo_discount": 0,
"count": 1,
"apply_discount": true
},
{
"article_id": 193672,
"current_price_without_promo": 79.99,
"promo_discount": 0,
"count": 1,
"apply_discount": true
},
{
"article_id": 261657,
"current_price_without_promo": 16.99,
"promo_discount": 0,
"count": 1,
"apply_discount": true
},
{
"article_id": 318153,
"current_price_without_promo": 13.99,
"promo_discount": 0,
"count": 1,
"apply_discount": true
}
],
"discount_params_per_article": [
{
"article_id": 311729,
"min_discount": 0,
"max_discount": 4.12,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
},
{
"article_id": 229752,
"min_discount": 0,
"max_discount": 7.52,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
},
{
"article_id": 193672,
"min_discount": 0,
"max_discount": 60,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
},
{
"article_id": 261657,
"min_discount": 0,
"max_discount": 12.4,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
},
{
"article_id": 318153,
"min_discount": 0,
"max_discount": 8,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
}
],
"target_probability_increase": null,
"request_time": "2019-12-21T21:32:13.018635"
},
"total_discount": 0.94,
"article_discounts": [
{
"article_id": 311729,
"discount": 0.04
},
{
"article_id": 229752,
"discount": 0.08
},
{
"article_id": 193672,
"discount": 0.61
},
{
"article_id": 261657,
"discount": 0.13
},
{
"article_id": 318153,
"discount": 0.08
}
]
}
我想做的是将原始 JSON 展平为 JSON-s 数组,如下所示:
[{
"discount_guid": "3afeb169-7969-4f6f-8928-d801692848b1",
"user_uid": 5467890,
"article_id": 318153,
"current_price_without_promo": 13.99,
"promo_discount": 0,
"count": 1,
"apply_discount": true,
"min_discount": 0,
"max_discount": 8,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1,
"target_probability_increase": null,
"request_time": "2019-12-21T21:32:13.018635",
"total_discount": 0.94,
"discount": 0.08
},
{
"discount_guid": ...
},
...
]
我已经设法通过这种方式获得了一个扁平的 JSON:
import groovy.json.JsonOutput as jo
def content = new File('response.json')
def slurper = new groovy.json.JsonSlurper()
def object = slurper.parseText(content)
def flattenMap(Map map) {
def result = [:]
map.each { k, v ->
if (v instanceof Map) {
result << flattenMap(v)
} else if (v instanceof Collection && v.every {it instanceof Map}) {
v.each {
result << flattenMap(it)
}
} else {
result[k] = v
}
}
result
}
println(jo.prettyPrint(jo.toJson(flattenMap(object))))
但我不知道如何获得完整的 JSON-s 数组。我确信有一种简单的方法可以实现这一点,但我对 Groovy 还是很陌生,到目前为止我还没有找到解决方案。任何帮助将不胜感激。
解决方案
解决这个问题的一种方法是这样的:
import groovy.json.*
def str = '''
{
"input_query": {
"discount_guid": "3afeb169-7969-4f6f-8928-d801692848b1",
"user_uid": 5467890,
"shopping_list": [
{
"article_id": 311729,
"current_price_without_promo": 7.69,
"promo_discount": 0,
"count": 1,
"apply_discount": true
},
{
"article_id": 229752,
"current_price_without_promo": 11.29,
"promo_discount": 0,
"count": 1,
"apply_discount": true
},
{
"article_id": 193672,
"current_price_without_promo": 79.99,
"promo_discount": 0,
"count": 1,
"apply_discount": true
},
{
"article_id": 261657,
"current_price_without_promo": 16.99,
"promo_discount": 0,
"count": 1,
"apply_discount": true
},
{
"article_id": 318153,
"current_price_without_promo": 13.99,
"promo_discount": 0,
"count": 1,
"apply_discount": true
}
],
"discount_params_per_article": [
{
"article_id": 311729,
"min_discount": 0,
"max_discount": 4.12,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
},
{
"article_id": 229752,
"min_discount": 0,
"max_discount": 7.52,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
},
{
"article_id": 193672,
"min_discount": 0,
"max_discount": 60,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
},
{
"article_id": 261657,
"min_discount": 0,
"max_discount": 12.4,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
},
{
"article_id": 318153,
"min_discount": 0,
"max_discount": 8,
"imposed_discount": null,
"article_target_probability_increase": 1.15,
"discount_downscale_factor": 1
}
],
"target_probability_increase": null,
"request_time": "2019-12-21T21:32:13.018635"
},
"total_discount": 0.94,
"article_discounts": [
{
"article_id": 311729,
"discount": 0.04
},
{
"article_id": 229752,
"discount": 0.08
},
{
"article_id": 193672,
"discount": 0.61
},
{
"article_id": 261657,
"discount": 0.13
},
{
"article_id": 318153,
"discount": 0.08
}
]
}
'''
def json = new JsonSlurper().parseText(str)
// a predicate to check if a value is a plain value vs map or list
def isPlain = { v -> !(v instanceof Map) && !(v instanceof List) }
// for the two maps json.input_query and the root level json map,
// find all plain values
def plainValues = json.input_query.findAll { k, v -> isPlain(v) } +
json.findAll { k, v -> isPlain(v) }
// find the three lists of maps, group by article_id and add the
// values for each article id to a cumulative map and finally
// add the plain values collected above to each cumulative map
def result = (json.input_query.shopping_list +
json.input_query.discount_params_per_article +
json.article_discounts).groupBy {
it.article_id
}.values().collect { listOfMaps ->
listOfMaps.sum() + plainValues
}
// print result
result.each { m ->
println "-----"
m.sort().each { k, v ->
println "${k.padLeft(35)} -> $v"
}
}
执行上述产生:
─➤ groovy solution.groovy
-----
apply_discount -> true
article_id -> 311729
article_target_probability_increase -> 1.15
count -> 1
current_price_without_promo -> 7.69
discount -> 0.04
discount_downscale_factor -> 1
discount_guid -> 3afeb169-7969-4f6f-8928-d801692848b1
imposed_discount -> null
max_discount -> 4.12
min_discount -> 0
promo_discount -> 0
request_time -> 2019-12-21T21:32:13.018635
target_probability_increase -> null
total_discount -> 0.94
user_uid -> 5467890
-----
apply_discount -> true
article_id -> 229752
article_target_probability_increase -> 1.15
count -> 1
current_price_without_promo -> 11.29
discount -> 0.08
discount_downscale_factor -> 1
discount_guid -> 3afeb169-7969-4f6f-8928-d801692848b1
imposed_discount -> null
max_discount -> 7.52
min_discount -> 0
promo_discount -> 0
request_time -> 2019-12-21T21:32:13.018635
target_probability_increase -> null
total_discount -> 0.94
user_uid -> 5467890
-----
...
最后的打印输出按键排序,并为可读性做了一些缩进。
然后,您可以使用以下方式获取输出 json:
def outputJson = JsonOutput.toJson(result)
推荐阅读
- sql - 从另一个查询的已返回结果中选择记录
- docker - 'docker networks' 信息保存在哪里
- react-native - Onpress 颜色变化
- python - 将 Django 项目从 Python 2 转换为 Python 3:如何修复 Python int OverFlowError?
- django - post_save 播放视频
- c# - 如何在json请求中路由方法
- c# - 功能递归模式目前处于预览阶段 Visual Studio 2019
- apache-kafka - 读取 Kafka 获取请求的 IO 大小
- r - TermDocumentMatrix 的“字典”参数在 R 中不起作用
- reactjs - TypeScript - 如何在可重用的 React 组件中使用泛型