Groovy 中的复杂 JSON 转换
Complex JSON transformation in Groovy
这个问题有点基于我以前的 。
来源JSON:
{
"reports": [
{
"columnHeader": {
"dimensions": [
"ga:date"
],
"metricHeader": {
"metricHeaderEntries": [
{
"name": "ga:sessions",
"type": "INTEGER"
},
{
"name": "ga:bounces",
"type": "INTEGER"
}
]
}
},
"data": {
"rows": [
{
"dimensions": [
"20210110"
],
"metrics": [
{
"values": [
"49",
"22"
]
}
]
},
{
"dimensions": [
"20210111"
],
"metrics": [
{
"values": [
"40",
"17"
]
}
]
}
],
"totals": [
{
"values": [
"149",
"64"
]
}
],
"rowCount": 2,
"minimums": [
{
"values": [
"40",
"17"
]
}
],
"maximums": [
{
"values": [
"60",
"25"
]
}
],
"isDataGolden": true
}
}
]
}
我需要使用上面 JSON 中的 metrics
数组创建 JSON。我应该遍历 data.rows.dimensions
并将 data.rows.metrics.values
映射到 columnHeader.metricHeader.metricHeaderEntries.name
(订单已正确保存)。或者遍历 metricHeaderEntries.name
并添加 values
和 report_date
。我不知道哪种方式是对的。因此,我需要一个包含字段 name
、value
、report_date
的数组指标,如上所述。此外,来源 JSON 中的 report_date
格式无效。 20210110
之类的值应转换为 2021-01-10
预期输出(或类似这样,但按 report_date 分组):
{
"metrics": [
{
"name": "ga:sessions",
"value": "49",
"report_date": "2021-01-10"
},
{
"name": "ga:sessions",
"type": "40",
"report_date": "2021-01-11"
},
{
"name": "ga:bounces",
"type": "22",
"report_date": "2021-01-10"
},
{
"name": "ga:bounces",
"type": "17",
"report_date": "2021-01-11"
}
],
"isDataGolden": true
}
更新
我试过这个脚本:
def data = new JsonSlurper().parseText(content)
def report = data.reports[0]
def rows = report.data.rows
def result = [
metrics : rows.indexed().collect{index, value ->
[
name : report.columnHeader.metricHeader.metricHeaderEntries.name[index],
value: value.metrics[0].values[index],
report_date: value.dimensions[0]
]
},
isDataGolden : report.isDataGolden
]
它returns:
{
"metrics":[
{
"name":"ga:sessions",
"value":"49",
"report_date":"20210110"
},
{
"name":"ga:bounces",
"value":"25",
"report_date":"20210111"
}
],
"isDataGolden": true
}
因此它不会遍历所有日期+指标组合。我想我需要一个嵌套循环?但是什么样的?
collect
始终是输入和输出之间的 1:1 映射。这样你就可以
不用于为每个输入创建多个输出;你必须使用
collectMany
,就是这样做的。
所以使用 collectMany
遍历所有行,然后 collect
遍历
header/values 个元组。
import groovy.json.JsonSlurper
def data = new JsonSlurper().parse("data.json" as File)
def report = data.reports[0]
def headers = report.columnHeader.metricHeader.metricHeaderEntries
println report.data.rows.collectMany{
[headers, it.metrics[0].values].transpose().collect{ h, v ->
[name: h.name, value: v, report_date: it.dimensions[0]]
}
}
// [[name:ga:sessions,
// value:49,
// report_date:20210110],
// [name:ga:bounces,
// value:22,
// report_date:20210110],
// [name:ga:sessions,
// value:40,
// report_date:20210111],
// [name:ga:bounces,
// value:17,
// report_date:20210111]]
这个问题有点基于我以前的
来源JSON:
{
"reports": [
{
"columnHeader": {
"dimensions": [
"ga:date"
],
"metricHeader": {
"metricHeaderEntries": [
{
"name": "ga:sessions",
"type": "INTEGER"
},
{
"name": "ga:bounces",
"type": "INTEGER"
}
]
}
},
"data": {
"rows": [
{
"dimensions": [
"20210110"
],
"metrics": [
{
"values": [
"49",
"22"
]
}
]
},
{
"dimensions": [
"20210111"
],
"metrics": [
{
"values": [
"40",
"17"
]
}
]
}
],
"totals": [
{
"values": [
"149",
"64"
]
}
],
"rowCount": 2,
"minimums": [
{
"values": [
"40",
"17"
]
}
],
"maximums": [
{
"values": [
"60",
"25"
]
}
],
"isDataGolden": true
}
}
]
}
我需要使用上面 JSON 中的 metrics
数组创建 JSON。我应该遍历 data.rows.dimensions
并将 data.rows.metrics.values
映射到 columnHeader.metricHeader.metricHeaderEntries.name
(订单已正确保存)。或者遍历 metricHeaderEntries.name
并添加 values
和 report_date
。我不知道哪种方式是对的。因此,我需要一个包含字段 name
、value
、report_date
的数组指标,如上所述。此外,来源 JSON 中的 report_date
格式无效。 20210110
之类的值应转换为 2021-01-10
预期输出(或类似这样,但按 report_date 分组):
{
"metrics": [
{
"name": "ga:sessions",
"value": "49",
"report_date": "2021-01-10"
},
{
"name": "ga:sessions",
"type": "40",
"report_date": "2021-01-11"
},
{
"name": "ga:bounces",
"type": "22",
"report_date": "2021-01-10"
},
{
"name": "ga:bounces",
"type": "17",
"report_date": "2021-01-11"
}
],
"isDataGolden": true
}
更新
我试过这个脚本:
def data = new JsonSlurper().parseText(content)
def report = data.reports[0]
def rows = report.data.rows
def result = [
metrics : rows.indexed().collect{index, value ->
[
name : report.columnHeader.metricHeader.metricHeaderEntries.name[index],
value: value.metrics[0].values[index],
report_date: value.dimensions[0]
]
},
isDataGolden : report.isDataGolden
]
它returns:
{
"metrics":[
{
"name":"ga:sessions",
"value":"49",
"report_date":"20210110"
},
{
"name":"ga:bounces",
"value":"25",
"report_date":"20210111"
}
],
"isDataGolden": true
}
因此它不会遍历所有日期+指标组合。我想我需要一个嵌套循环?但是什么样的?
collect
始终是输入和输出之间的 1:1 映射。这样你就可以
不用于为每个输入创建多个输出;你必须使用
collectMany
,就是这样做的。
所以使用 collectMany
遍历所有行,然后 collect
遍历
header/values 个元组。
import groovy.json.JsonSlurper
def data = new JsonSlurper().parse("data.json" as File)
def report = data.reports[0]
def headers = report.columnHeader.metricHeader.metricHeaderEntries
println report.data.rows.collectMany{
[headers, it.metrics[0].values].transpose().collect{ h, v ->
[name: h.name, value: v, report_date: it.dimensions[0]]
}
}
// [[name:ga:sessions,
// value:49,
// report_date:20210110],
// [name:ga:bounces,
// value:22,
// report_date:20210110],
// [name:ga:sessions,
// value:40,
// report_date:20210111],
// [name:ga:bounces,
// value:17,
// report_date:20210111]]