json - 在 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
]
我应该怎么办:
- 基于
action_type
. 因此,如果源 JSON 中的数组包含action_type
我应该遍历这个数组并执行以下步骤。 - 为每个添加
ad_id
,impression_device
, - 它们对于预期 JSON 中的所有数组都是相同的。publisher_platform
action_type
- Set
field_name
:它是一个 JSON 数组名称action_type
: 例如:
"actions" : [ {
"action_type" : "video_view",
"value" : "1"
}, {
"action_type" : "post_engagement",
"value" : "1"
} ]
field_name
应该是actions
。
- 还有问题。一些 JSON 可能包含
actions
,unique_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"
}
]
解决方案
直截了当的东西:
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 ] ?: '' ] }
推荐阅读
- flutter - 带有居中的小部件上的小部件
- r - 如何编写一个删除R中行数据的for循环
- css - X 的所有后代以及 X 本身是否有一个 CSS 选择器?
- flutter - Flutter List 未在异步方法之外更新
- regex - 如何从 Clojure 中的组件构建正则表达式?
- reactjs - getItemAsync 返回 null 或以前的值
- elasticsearch - 用于过滤嵌套数组对象的无痛 Elasticsearch 脚本
- ruby-on-rails - 预编译资产失败 - 远程拒绝
- git - 无法弄清楚如何克隆存储库
- flutter - Flutter 视频播放器无法加载资产视频