首页 > 解决方案 > 在 Groovy 中修改 JSON

问题描述

我有一个 JSON:

{
  "ad_id" : "795220717",
  "date_start" : "2021-03-02",
  "account_currency" : "EUR",
  "account_name" : "Bonduelle",
  "actions" : [ {
    "action_type" : "video_view",
    "value" : "1"
  }, {
    "action_type" : "post_engagement",
    "value" : "1"
  } ],
  "buying_type" : "AUCTION",
  "clicks" : "241",
  "cost_per_action_type" : [ {
    "action_type" : "video_view",
    "value" : "0.010006"
  }, {
    "action_type" : "page_engagement",
    "value" : "0.010006"
  }, {
    "action_type" : "post_engagement",
    "value" : "0.010006"
  } ],
  "cost_per_unique_action_type" : [ {
    "action_type" : "video_view",
    "value" : "0.010006"
  }, {
    "action_type" : "page_engagement",
    "value" : "0.010006"
  }, {
    "action_type" : "post_engagement",
    "value" : "0.010006"
  } ],
  "cpm" : "10.005512",
  "ctr" : "0",
  "spend" : "0.010006",
  "unique_actions" : [ {
    "action_type" : "video_view",
    "value" : "1"
  }, {
    "action_type" : "page_engagement",
    "value" : "1"
  }, {
    "action_type" : "post_engagement",
    "value" : "1"
  } ],
  "unique_clicks" : "13",
  "video_avg_time_watched_actions" : [ {
    "action_type" : "video_view",
    "value" : "5"
  } ],
  "video_p25_watched_actions" : [ {
    "action_type" : "video_view",
    "value" : "1"
  } ],
  "video_play_actions" : [ {
    "action_type" : "video_view",
    "value" : "1"
  } ],
  "created_time" : "2021-02-19",
  "impression_device" : "other",
  "publisher_platform" : "instagram",
  "platform_position" : "feed"
}

转换后的预期 JSON:

[ {
    "ad_id" : "795220717",
    "impression_device" : "other",
    "publisher_platform" : "instagram",
    "action_type" : "video_view",
    "value" : "1",
    "field_name": "actions"
  }, {
    "ad_id" : "795220717",
    "impression_device" : "other",
    "publisher_platform" : "instagram",
    "action_type" : "post_engagament",
    "value" : "1",
    "field_name": "actions"
  }, {
    "ad_id" : "795220717",
    "impression_device" : "other",
    "publisher_platform" : "instagram",
    "action_type" : "post_engagament",
    "value" : "0.010006",
    "field_name": "cost_per_action_type"
   }, 
 ... etc
]

我应该怎么办:

  1. 基于action_type. 因此,如果源 JSON 中的数组包含action_type我应该遍历这个数组并执行以下步骤。
  2. 为每个添加ad_id, impression_device, - 它们对于预期 JSON 中的所有数组都是相同的。publisher_platformaction_type
  3. Set field_name:它是一个 JSON 数组名称action_type: 例如:
 "actions" : [ {
    "action_type" : "video_view",
    "value" : "1"
  }, {
    "action_type" : "post_engagement",
    "value" : "1"
  } ]

field_name应该是actions

  1. 还有问题。一些 JSON 可能包含actionsunique_actions但不包含cost_per_action_type. 所以我不能根据这些名称循环遍历,我应该遍历所有 JSON 键并查找并找到那些是数组并包含action_type在其中的键。

我不知道从哪里开始。尝试从:

def slurped = new JsonSlurper().parseText(content)
def map = slurped.findAll { 
   it.key instanceof List
}

但它返回空地图。我需要解决的第一个问题:如何过滤 JSON 中包含的数组action_type

更新

JSON 内部包含多个元素:

[
   {
      "ad_id":"795220717",
      "date_start":"2021-03-02",
      "actions":[
         {
            "action_type":"video_view",
            "value":"1"
         },
         {
            "action_type":"post_engagement",
            "value":"1"
         }
      ],
      "buying_type":"AUCTION",
      "clicks":"241",
      "cost_per_action_type":[
         {
            "action_type":"video_view",
            "value":"0.010006"
         },
         {
            "action_type":"page_engagement",
            "value":"0.010006"
         },
         {
            "action_type":"post_engagement",
            "value":"0.010006"
         }
      ],
      "cost_per_unique_action_type":[
         {
            "action_type":"video_view",
            "value":"0.010006"
         },
         {
            "action_type":"page_engagement",
            "value":"0.010006"
         },
         {
            "action_type":"post_engagement",
            "value":"0.010006"
         }
      ],
      "cpm":"10.005512",
      "ctr":"0",
      "spend":"0.010006",
      "unique_clicks":"13",
      "created_time":"2021-02-19",
      "impression_device":"other",
      "publisher_platform":"instagram",
      "platform_position":"feed"
   },
   {
      "ad_id":"220717",
      "date_start":"2021-03-02",
      "account_currency":"USD",
      "account_name":"Nestle",
      "actions":[
         {
            "action_type":"video_view",
            "value":"1"
         },
         {
            "action_type":"post_engagement",
            "value":"1"
         }
      ],
      "buying_type":"AUCTION",
      "clicks":"241",
      "cpm":"10.005512",
      "ctr":"0",
      "spend":"0.010006",
      "video_avg_time_watched_actions":[
         {
            "action_type":"video_view",
            "value":"5"
         }
      ],
      "video_p25_watched_actions":[
         {
            "action_type":"video_view",
            "value":"1"
         }
      ],
      "video_play_actions":[
         {
            "action_type":"video_view",
            "value":"1"
         }
      ],
      "created_time":"2021-02-19",
      "impression_device":"other",
      "publisher_platform":"instagram",
      "platform_position":"feed"
   }
]

标签: jsongroovy

解决方案


直截了当的东西:

import groovy.json.*

String s = '''
{
  "ad_id" : "795220717",
  "date_start" : "2021-03-02",
  "account_currency" : "EUR",
  "account_name" : "Bonduelle",
  "actions" : [ {
    "action_type" : "video_view",
    "value" : "1"
  }, {
    "action_type" : "post_engagement",
    "value" : "1"
  } ],
  "buying_type" : "AUCTION",
  "clicks" : "241",
  "cost_per_action_type" : [ {
    "action_type" : "video_view",
    "value" : "0.010006"
  }, {
    "action_type" : "page_engagement",
    "value" : "0.010006"
  }, {
    "action_type" : "post_engagement",
    "value" : "0.010006"
  } ],
  "cost_per_unique_action_type" : [ {
    "action_type" : "video_view",
    "value" : "0.010006"
  }, {
    "action_type" : "page_engagement",
    "value" : "0.010006"
  }, {
    "action_type" : "post_engagement",
    "value" : "0.010006"
  } ],
  "cpm" : "10.005512",
  "ctr" : "0",
  "spend" : "0.010006",
  "unique_actions" : [ {
    "action_type" : "video_view",
    "value" : "1"
  }, {
    "action_type" : "page_engagement",
    "value" : "1"
  }, {
    "action_type" : "post_engagement",
    "value" : "1"
  } ],
  "unique_clicks" : "13",
  "video_avg_time_watched_actions" : [ {
    "action_type" : "video_view",
    "value" : "5"
  } ],
  "video_p25_watched_actions" : [ {
    "action_type" : "video_view",
    "value" : "1"
  } ],
  "video_play_actions" : [ {
    "action_type" : "video_view",
    "value" : "1"
  } ],
  "created_time" : "2021-02-19",
  "impression_device" : "other",
  "publisher_platform" : "instagram",
  "platform_position" : "feed"
}'''

Map json = new JsonSlurper().parseText s

Map common = json.findAll{ k, _ -> k in [ 'ad_id', 'impression_device', 'publisher_platform' ] }

List result = json.inject( [] ){ res, k, v ->
  if( ( v in List ) && v.any{ it.action_type } ) v.each{ res << common + [ field_name:k ] + it }
  res
}

JsonOutput.prettyPrint JsonOutput.toJson( result )

印刷:

[
    {
        "ad_id": "795220717",
        "impression_device": "other",
        "publisher_platform": "instagram",
        "field_name": "actions",
        "action_type": "video_view",
        "value": "1"
    },
    {
        "ad_id": "795220717",
        "impression_device": "other",
        "publisher_platform": "instagram",
        "field_name": "actions",
        "action_type": "post_engagement",
        "value": "1"
    },
    {
        "ad_id": "795220717",
        "impression_device": "other",
        "publisher_platform": "instagram",
        "field_name": "cost_per_action_type",
        "action_type": "video_view",
        "value": "0.010006"
    },
    etc...
]

更新:

在地图列表的情况下,代码会发生一些变化:

import groovy.json.*

String s = '''
[ {
  "ad_id" : "795220717",
   etc....
} ]'''

List json = new JsonSlurper().parseText s

List result = json.inject( [] ){ res, elem ->
  Map common = elem.findAll{ k, _ -> k in [ 'ad_id', 'impression_device', 'publisher_platform' ] }
  elem.each{ k, v ->
    if( ( v in List ) && v.any{ it.action_type } ) v.each{ res << common + [ field_name:k ] + it }
  }
  res
}

输出保持不变

更新 2:

  Map common = [ 'ad_id', 'impression_device', 'publisher_platform' ].collectEntries{ [ it, elem[ it ] ?: '' ] }

推荐阅读