Parsing nested json data using Python - python

[
{
"asset_id": 49,
"status": "success",
"name": "de1",
"app": "CCid",
"action_results": [
{
"status": "success",
"data": [
{
"report": {
"status": {
"origin": "sa",
"status": "Up.",
"sha1": "4a",
"sample_started_at": 159,
"running_on": "mt",
"ran": true,
"auto": true,
"vm": "w"
},
"artifacts": {
"1": {
"size": 599518,
"mime-type": "applic=binary",
"antivirus": {
"reversing_labs": {
"status": "UNKNOWN",
"scanner_count": 0,
"scanner_match": 0,
"threat_name": "",
"query_hash": {
"sha256": "029"
},
"last_seen": "0001-01-01T00:00:00Z"
}
},
"entropy": 7.9870740440306
},
"10": {
"size": 599518,
"mime-type": "applic=binary",
"antivirus": {
"reversing_labs": {
"status": "UNKNOWN",
"scanner_count": 0,
"scanner_match": 0,
"threat_name": "",
"query_hash": {
"sha256": "d38"
},
"last_seen": "0001-01-01T00:00:00Z"
}
},
"entropy": 1
}
}
}
}
],
"app_id": 15
}
]
}
]
I am trying to access scanner count and scanner match values using python But not getting the required result.
action_results = results[0].get('action_results', [])
action_status = action_results[0].get('status', 'failed')
results_data = action_results[0].get('data', [])
sandbox_report = results_data[0].get('report', {})
for key,value in sandbox_report.items():
if key == "artifacts":
artifacts = list()
for each_key, each_value in value.items():
for i in each_value:
if i == "antivirus":
artifact_item = dict()
reversing_labs = i.get('reversing_labs', {})
artifact_item['scanner_count'] = reversing_labs.get('scanner_count', 0)
Can anyone point out whats wrong ?

You can try
action_results = results[0].get('action_results', [])
action_status = action_results[0].get('status', 'failed')
results_data = action_results[0].get('data', [])
sandbox_report = results_data[0].get('report', {})
artifact_item = dict()
for key,value in sandbox_report.items():
if key == "artifacts":
artifacts = list()
for each_key, each_value in value.items():
for k, v in each_value.items():
if k == "antivirus":
reversing_labs = v.get('reversing_labs', {})
artifact_item[key] = [{'scanner_count' : reversing_labs.get('scanner_count', 0)},
{'scanner_match' : reversing_labs.get('scanner_match', 0)}]
print(artifact_item)
Output
{'artifacts': [{'scanner_count': 0}, {'scanner_match': 0}]}
This code will extract the values of scanner_count and scanner_match in a list in a dictionary that the key value is artifacts.

this is how i'd do it.
jsonData = json.loads(results)
nested = jsonData[0]['action_results'][0]['data'][0]['report']['artifacts']
for artifact in nested:
print(f"Scanner count = {nested[artifact]['antivirus']['reversing_labs']['scanner_count']}")
print(f"Scanner match = {nested[artifact]['antivirus']['reversing_labs']['scanner_match']}")

Related

How to change json key name with python

Need some help please.
I have a similar json file:
{
"timestamp": "2022-09-20T08:16:00.000Z",
"metadata": {
"orgID": "6780",
"projectId": 0988,
}
},
{
"data":
"workers": [
{
"identifiers": {
"FullName": null,
"NINumber": null,
"CompID": null
},
"lastName": null,
"costCenter": null
},
{
"codes": [
{
"source": {
"name": "net_salary",
"value": 11500
},
"name": "net_salary",
"code": "rt_sa",
"value": 11500
},
{
"identifiers": {
"FullName": null,
"NINumber": null,
Comp ID": null
},
"lastName": null,
"costCenter": null
},
{
"codes": [
{
"source": {
"name": "hiredate",
"value": 3.333
},
"name": "hiredate",
"code": "h_code",
"value": 3.333
},
I want to change the key names under source from name->fieldname and value to fieldvalue.
However, I don't want to change the keys where there are the keys: name, code, value.
I tried this but it is not correct:
with open(r'C:\Users\Administrator\Documents\test\PJSON.json') as f:
payrolldata = json.load(f)
source = payrolldata[1]['data']['workers'][1]['codes'][1]['source']
print(source)
oldvalue = source.keys()
print(str(oldvalue).replace('name', 'newname').replace('value', 'value2'))
payrolldata = str(oldvalue).replace('name', 'newname').replace('value', 'newvalue2')
for d in payrolldata:
d['newName':] = d.pop["'name':"]
with open(r'C:\Users\Administrator\Documents\test\PJSON.json', "w") as f:
json.dump(payrolldata, f, indent=4)
I suggest you don't convert your dict into string and use something like this on you dict read from json file (with json.load)
def deep_replace_key(
d,
old_key: str,
new_key: str,
branch_name: str = None,
replace: bool = False,
):
"""deep replace key in dict.
Only make replacement if the we are in the branch branch_name."""
if branch_name is None:
replace = True
if isinstance(d, dict):
d_copy = d.copy()
for key, value in d_copy.items():
if key == old_key and replace:
d[new_key] = d.pop(old_key)
else:
if branch_name and key == branch_name:
deep_replace_key(value, old_key, new_key, branch_name, True)
else:
deep_replace_key(value, old_key, new_key, branch_name, False)
elif isinstance(d, list):
for item in d:
deep_replace_key(item, old_key, new_key, branch_name, replace)
return d
Here is a working test for this code
import unittest
# test
class TestDeepReplaceKey(unittest.TestCase):
def test_deep_replace_key(self):
d = {
"codes": [
{
"source": {
"name": "hiredate",
"value": 3.333
},
"not_source": {
"name": "hiredate",
"value": 3.333
},
},
{
"source": {
"name": "hiredate",
"value": 3.333
},
"not_source": {
"name": "hiredate",
"value": 3.333
},
},
]
}
d = deep_replace_key(d, "name", "new_name", "source", )
self.assertEqual(d["codes"][0]["source"]["new_name"], "hiredate")
self.assertEqual(d["codes"][0]["not_source"]["name"], "hiredate")
d = deep_replace_key(d, "name", "new_name", )
self.assertEqual(d["codes"][0]["not_source"]["new_name"], "hiredate")
So you can see if I call deep_replace_key(d, "name", "new_name", "source", ) the change only happens in the source block.
If I omit mentioning "source" like this deep_replace_key(d, "name", "new_name", ) change happens everywhere.

Python equivalent of PHP http_build_query

Here is the PHP code that I want to write in Python.
<?php
$json = '{
"targeting": [
{
"country": {
"allow": [
"US",
"DE"
]
},
"region" : {
"allow" : {
"US" : [
33
],
"DE" : [
10383
]
}
},
"city": {
"allow": {
"US": [
57
],
"DE": [
3324
]
}
},
"os": {
"allow": [
{
"name": "Android",
"comparison": "GTE",
"version": "2.3.1"
},
{
"name": "Apple TV Software",
"comparison": "EQ",
"version": "4.4"
},
{
"name": "Windows",
"comparison": "EQ",
"version": "Vista"
}
]
},
"isp" : {
"allow" : {
"US" : [
"Att"
],
"DE" : [
"Telekom"
]
}
},
"ip": {
"allow": [
"11.12.13.0-17.18.19.22",
"6.0.0.0",
"10.0.0.0-10.0.0.2",
"11.0.0.0/24"
]
},
"device_type": [
"mobile"
],
"browser": {
"allow": [
"Yandex.Browser for iOS",
"SlimBrowser",
"Edge Mobile"
]
},
"brand": {
"allow": [
"Smartbook Entertainment",
"Walton",
"PIPO"
]
},
"sub": {
"allow": {
"1": [
"A",
"B"
]
},
"deny": {
"2": [
"C",
"D"
]
},
"deny_groups": [
{
"1": ""
},
{
"1": "X",
"2": "Y"
}
]
},
"connection": [
"wi-fi",
"cellular"
],
"block_proxy": true,
"affiliate_id": [
1
],
"url": "http://test-url.com"
}
]
}';
$arr = json_decode($json);
$postData = http_build_query($arr);
//POST SomeURLhere
echo urldecode($arr);
What I need is to send this json in this format
targeting[0][country][allow][]=TR
targeting[0][os][allow][][name]=iOS
targeting[1][country][allow][]=DE
targeting[1][os][allow][][name]=iOS
I guess I need to figure out how to use http_build_query in Python.
with referring this answer I found the solution.
from collections.abc import MutableMapping
from urllib.parse import urlencode, unquote
def flatten(dictionary, parent_key=False, separator='.', separator_suffix=''):
"""
Turn a nested dictionary into a flattened dictionary
:param dictionary: The dictionary to flatten
:param parent_key: The string to prepend to dictionary's keys
:param separator: The string used to separate flattened keys
:return: A flattened dictionary
"""
items = []
for key, value in dictionary.items():
new_key = str(parent_key) + separator + key + separator_suffix if parent_key else key
if isinstance(value, MutableMapping):
items.extend(flatten(value, new_key, separator, separator_suffix).items())
elif isinstance(value, list) or isinstance(value, tuple):
for k, v in enumerate(value):
items.extend(flatten({str(k): v}, new_key, separator, separator_suffix).items())
else:
items.append((new_key, value))
return dict(items)
req = {'check': 'command', 'parameters': ({'parameter': '1', 'description':
'2'}, {'parameter': '3', 'description': '4'})}
req = flatten(req, False, '[', ']')
query = urlencode(req)
query_parsed = unquote(query)
print(query)
print(query_parsed)
And the outputs:
check=command&parameters%5B0%5D%5Bparameter%5D=1&parameters%5B0%5D%5Bdescription%5D=2&parameters%5B1%5D%5Bparameter%5D=3&parameters%5B1%5D%5Bdescription%5D=4
check=command&parameters[0][parameter]=1&parameters[0][description]=2&parameters[1][parameter]=3&parameters[1][description]=4

Create dynamic json object in python

I have a dictionary which is contain multiple keys and values and the values also contain the key, value pair. I am not getting how to create dynamic json using this dictionary in python. Here's the dictionary:
image_dict = {"IMAGE_1":{"img0":"IMAGE_2","img1":"IMAGE_3","img2":"IMAGE_4"},"IMAGE_2":{"img0":"IMAGE_1", "img1" : "IMAGE_3"},"IMAGE_3":{"img0":"IMAGE_1", "img1":"IMAGE_2"},"IMAGE_4":{"img0":"IMAGE_1"}}
My expected result like this :
{
"data": [
{
"image": {
"imageId": {
"id": "IMAGE_1"
},
"link": {
"target": {
"id": "IMAGE_2"
},
"target": {
"id": "IMAGE_3"
},
"target": {
"id": "IMAGE_4"
}
}
},
"updateData": "link"
},
{
"image": {
"imageId": {
"id": "IMAGE_2"
},
"link": {
"target": {
"id": "IMAGE_1"
},
"target": {
"id": "IMAGE_3"
}
}
},
"updateData": "link"
},
{
"image": {
"imageId": {
"id": "IMAGE_3"
},
"link": {
"target": {
"id": "IMAGE_1"
},
"target": {
"id": "IMAGE_2"
}
}
},
"updateData": "link"
} ,
{
"image": {
"imageId": {
"id": "IMAGE_4"
},
"link": {
"target": {
"id": "IMAGE_1"
}
}
},
"updateData": "link"
}
]
}
I tried to solve it but I didn't get expected result.
result = {"data":[]}
for k,v in sorted(image_dict.items()):
for a in sorted(v.values()):
result["data"].append({"image":{"imageId":{"id": k},
"link":{"target":{"id": a}}},"updateData": "link"})
print(json.dumps(result, indent=4))
In Python dictionaries you can't have 2 values with the same key. So you can't have multiple targets all called "target". So you can index them. Also I don't know what this question has to do with dynamic objects but here's the code I got working:
import re
dict_res = {}
ind = 0
for image in image_dict:
lin_ind = 0
sub_dict = {'image' + str(ind): {'imageId': {image}, 'link': {}}}
for sub in image_dict[image].values():
sub_dict['image' + str(ind)]['link'].update({'target' + str(lin_ind): {'id': sub}})
lin_ind += 1
dict_res.update(sub_dict)
ind += 1
dict_res = re.sub('target\d', 'target', re.sub('image\d', 'image', str(dict_res)))
print dict_res

compare two json objects and remove the element and then compare resultant json to other json file

Python newbie:
Default.json
{
"name": {
"provide": ""
},
"test": {
"Fail": {
"centers": None,
"Nearest": 0
},
"far": "",
"Meta": null,
"Only": false,
"Tags": null
},
"Session": "",
"conf": {
"check": "",
"Reg": ""
},
"Token": ""
}
Remote.json
[ {
'name': {
'provide': ''
},
'Name': 'abc',
'test': {
'Service': 'redis',
'Tags': [
'stage'
],
'Fail': {
'centers': None,
'Nearest': 3
},
'Only': false,
'far': '',
'Meta': null
},
'Token': '',
'Session': '',
'conf': {
'Reg': '',
'check': 'name_prefix_match'
},
} ]
I have a default.json and remote .json .Task I am trying to achieve is remove all the json elements from the remote.json for whom the values of remote.json matches with the default.json.For example since the key,value of name:{provider=""} from default.json matches the name:{provider=""} from remote.json.It should get removed from remote.json
with open(remote.json) as f:
with open(default.json) as m:
file=json.load(f)
default=json.load(m)
for i in xrange(len(file)):
for key,value in default.items():
#default[key]=value
#a=filter(lambda x: x[""],file.keys())
1.I am not getting the idea here how to get key, value from default and compare it with file?Any help would be appreciated.
The reason I need to remove element from remote.json is because I need to compare the resultant json with other json file "local.json".If i dont' remove the key ,values with value "" or null or None then the comparison between remote.json and local.json would never be equal.
2.Is there any better way of going for this problem?
local.json
{
"Name": "",
"conf": {
"check": "name_prefix_match",
},
"test": {
"Service": "redis",
"Fail": {
"Near": 3
},
"Tags": ""
}
}
There are some problems with JSON examples because of None & False are not valid JSON objects (and so are single-quoted string literals), so let's pretend that we've already parsed files and got something like
default_json = {
"name": {
"provide": ""
},
"test": {
"Fail": {
"centers": None,
"Nearest": 0
},
"far": "",
"Meta": None,
"Only": False,
"Tags": None
},
"Session": "",
"conf": {
"check": "",
"Reg": ""
},
"Token": ""
}
remote_json = [{
"name": {
"provide": ""
},
"Name": "abc",
"test": {
"Service": "redis",
"Tags": [
"stage"
],
"Fail": {
"centers": None,
"Nearest": 3
},
"Only": False,
"far": "",
"Meta": None
},
"Token": "",
"Session": "",
"conf": {
"Reg": "",
"check": "name_prefix_match"
},
}]
Assuming that remote.json is the list of dictionaries & each one of them should be filtered out using default.json:
filtered_remote_json = [dict(item
for item in dictionary.items()
if item not in default_json.items())
for dictionary in remote_json]
will give us
filtered_remote_json == [{"Name": "abc",
"test": {"Service": "redis", "Tags": ["stage"],
"Fail": {"centers": None,
"Nearest": 3}, "Only": False,
"far": "", "Meta": None},
"conf": {"Reg": "",
"check": "name_prefix_match"}}]
EDIT
if we need to filter sub-dictionaries as well, then next a bit nasty utility function should help
def filter_defaults(json_object, default_json_object):
result = {}
for key, value in json_object.items():
try:
default_value = default_json_object[key]
except KeyError:
# key not in defaults, adding to result
result[key] = value
continue
# we need to process sub-dictionaries as well
if isinstance(value, dict):
value = filter_defaults(value, default_value)
# we are not interested in empty filtered sub-dictionaries
if not value:
continue
# value should differ from default
elif value == default_value:
continue
result[key] = value
return result
then just write
filtered_remote_json = [filter_defaults(dictionary, default_json)
for dictionary in remote_json]
this will give us
filtered_remote_json == [{"Name": "abc",
"test": {"Service": "redis", "Tags": ["stage"],
"Fail": {"Nearest": 3}},
"conf": {"check": "name_prefix_match"}}]

Convert float string to float in json

I have a json(test.json) file with the below data. I have around 10000 records. I need to convert value from string to float write in the new file(test1.json). How can I do do this from Python?
{
"name":"test001",
"cat":"test",
"loc":"x loc",
"ings":[
{
"name":"rrrrrr",
"value":"13.0"
},
{
"name":"hhhh",
"value":"18.0"
}
],
"nums":[
{
"name":"kkkk",
"value":"82.05"
},
{
"name":"uuuuu",
"value":"53.55"
}
]
},
{
"name":"test002",
"cat":"test1",
"loc":"y loc",
"ings":[
{
"name":"trtrtr",
"value":"11.0"
},
{
"name":"wewew",
"value":"19.0"
}
],
"nums":[
{
"name":"iuyt",
"value":"122.05"
},
{
"name":"oiui",
"value":"15.5"
}
]
}
resulting json file(test1.json) should be like below...
{
"name":"test001",
"cat":"test",
"loc":"x loc",
"ings":[
{
"name":"rrrrrr",
"value":13.0
},
{
"name":"hhhh",
"value":18.0
}
],
"nums":[
{
"name":"kkkk",
"value":82.05
},
{
"name":"uuuuu",
"value":53.55
}
]
},
{
"name":"test002",
"cat":"test1",
"loc":"y loc",
"ings":[
{
"name":"trtrtr",
"value":11.0
},
{
"name":"wewew",
"value":19.0
}
],
"nums":[
{
"name":"iuyt",
"value":122.05
},
{
"name":"oiui",
"value":15.5
}
]
}
You can provide an object_hook to the json.loads method which will allow you to modify any object (dicts) found within the json:
import json
json_data = """
[{
"name":"test001",
"cat":"test",
"loc":"x loc",
"ings":[
{
"name":"rrrrrr",
"value":"13.0"
},
{
"name":"hhhh",
"value":"18.0"
}
],
"nums":[
{
"name":"kkkk",
"value":"82.05"
},
{
"name":"uuuuu",
"value":"53.55"
}
]
},
{
"name":"test002",
"cat":"test1",
"loc":"y loc",
"ings":[
{
"name":"trtrtr",
"value":"11.0"
},
{
"name":"wewew",
"value":"19.0"
}
],
"nums":[
{
"name":"iuyt",
"value":"122.05"
},
{
"name":"oiui",
"value":"15.5"
}
]
}]
"""
def as_float(obj):
"""Checks each dict passed to this function if it contains the key "value"
Args:
obj (dict): The object to decode
Returns:
dict: The new dictionary with changes if necessary
"""
if "value" in obj:
obj["value"] = float(obj["value"])
return obj
if __name__ == '__main__':
l = json.loads(json_data, object_hook=as_float)
print (json.dumps(l, indent=4))
This results in what you want:
[
{
"loc": "x loc",
"ings": [
{
"name": "rrrrrr",
"value": 13.0
},
{
"name": "hhhh",
"value": 18.0
}
],
"name": "test001",
"nums": [
{
"name": "kkkk",
"value": 82.05
},
{
"name": "uuuuu",
"value": 53.55
}
],
"cat": "test"
},
{
"loc": "y loc",
"ings": [
{
"name": "trtrtr",
"value": 11.0
},
{
"name": "wewew",
"value": 19.0
}
],
"name": "test002",
"nums": [
{
"name": "iuyt",
"value": 122.05
},
{
"name": "oiui",
"value": 15.5
}
],
"cat": "test1"
}
]
To write to a file instead:
with open("out.json", "w+") as out:
json.dump(l, out, indent=4)
You would need to recursively traverse the data and convert anything that looks like a float to a float:
def fix_floats(data):
if isinstance(data,list):
iterator = enumerate(data)
elif isinstance(data,dict):
iterator = data.items()
else:
raise TypeError("can only traverse list or dict")
for i,value in iterator:
if isinstance(value,(list,dict)):
fix_floats(value)
elif isinstance(value,str):
try:
data[i] = float(value)
except ValueError:
pass
It should do the trick:
my_data = [
{ "name" : "rrrrrr",
"value" : "13.0" },
{ "name" : "hhhh",
"value" : "18.0" },
]
fix_floats(my_data)
>>> my_data
[{'name': 'rrrrrr', 'value': 13.0}, {'name': 'hhhh', 'value': 18.0}]
If you have a single or specific key value object, you can reiterate the value containing alphabetical strings or numerical strings, then map and check against their type with string.isnumeric():
dict = { 'a':'100', 'b':'200', 'c':'300', 'd':'four_hundred', 'e':'500' }
dict_parse = {k: int(v) if v.isnumeric() else v for k, v in dict.items()}
>>> dict_parse
{ 'a': 100, 'b': 200, 'c': 300, 'd':'four_hundred', 'e':500}
when dealing with float numbers amend the if statement to replace decimal point, you can apply same principal to negative numbers:
dict = { 'a':'10.0', 'b':'20.12', 'c':'300.3', 'd':'four_hundred', 'e':'500' }
dict_parse = {k: float(v) if v.replace(".", "").isnumeric() else v for k, v in dict.items()}
>>> dict_parse
{ 'a': 10.0, 'b': 20.12, 'c': 300.3, 'd':'four_hundred', 'e':500}

Categories