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 并添加 valuesreport_date。我不知道哪种方式是对的。因此,我需要一个包含字段 namevaluereport_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]]