Reputation: 746
I have a 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"
}
Expected JSON after transformations:
[ {
"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
]
What should I do:
action_type
. So if array in source JSON contains action_type
I should loop through this array and perform steps below.ad_id
, impression_device
, publisher_platform
for each action_type
- they will be the same for all arrays inside expected JSON.field_name
: it is a JSON array name for action_type
:
For example: "actions" : [ {
"action_type" : "video_view",
"value" : "1"
}, {
"action_type" : "post_engagement",
"value" : "1"
} ]
field_name
should be actions
.
actions
, unique_actions
but don't contain cost_per_action_type
. So I cant loop through based on these names and I should loop through all JSON keys and find and find those that are an array and contain action_type
inside.I don't know where begin. Tried to start with:
def slurped = new JsonSlurper().parseText(content)
def map = slurped.findAll {
it.key instanceof List
}
But it returns empty map. First question I need to solve: how to filter arrays inside JSON which contains action_type
?
UPDATE
JSON with multiple elements inside:
[
{
"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"
}
]
Upvotes: 0
Views: 203
Reputation: 20699
Something straight-forward:
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 )
prints:
[
{
"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...
]
UPDATE:
In case of List of Maps the code changes a bit:
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
}
The output remains the same
UPDATE 2:
Map common = [ 'ad_id', 'impression_device', 'publisher_platform' ].collectEntries{ [ it, elem[ it ] ?: '' ] }
Upvotes: 3
Reputation: 171084
Another alternative would be:
def model = new JsonSlurper().parseText(json)
def entries = { data, field ->
data."$field".collect {
[
'ad_id': data.ad_id,
'impression_device': data.impression_device,
'publisher_platform': data.publisher_platform,
'action_type': it.action_type,
'value': it.value,
'field_name': field
]
}
}
def result = entries(model, 'actions') + entries(model, 'cost_per_action_type')
JsonOutput.prettyPrint JsonOutput.toJson(result)
Upvotes: 1