我可以在编写Groovy脚本时使用一些帮助,以基于嵌套数组元素将JSON展平并拆分为多个JSON。这是原始的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
-----
...
末尾的打印输出按键排序,并进行一些缩进以提高可读性。