comparing elements of json in python - python

I do have a sample json as below:
{
"parent": [
{
"code": "333",
"priority": {
"p": "BB"
}
},
{
"code": "999",
"priority": {
"p": "BX"
}
},
{
"code": "2222",
"priority": {
"p": "BA"
}
}
]
}
This is just a sample json. I want to compare the value of p(priority) and based on that return corresponding code which has highest priority. Like in above sample json, 999 is the value that I am expecting since the value of p is BX which has highest priority. Is there a short cut and efficient way in python since I am new to python?
Update/clarification on Question:
Since I got answer based on the assumption that p is having alphabetic value which we can prioritize. But, that is not the case. P could have 3 set of values(which are fixed for example: BX is highest priority,BB is second and BA is least). If this json has priority BX, I need to return 999, if BX is not there but BB and BA are there, I need to return BB.
This was my basic solution which works but I think it has to many conditions:
code = None
for item in json['parent']:
if item['priority'] is not None and item['priority']['p'] is not None and item['priority']['p'] == 'BX' \
and item['code'] is not None:
code = item['code']
if item['priority'] is not None and item['priority']['p'] is not None and item['priority']['p'] == 'BB' \
and item['code'] is not None and code is not 'BX':
code = item['code']
if item['priority'] is not None and item['priority']['p'] is not None and item['priority']['p'] == 'BA' \
and item['code'] is not None and code is not 'BX' and code is not 'BB':
code = item['code']

You can utilise the argmin function from numpy:
import numpy as np
json = {
"parent": [
{
"code": "333",
"priority": {
"p": "B"
}
},
{
"code": "999",
"priority": {
"p": "A"
}
},
{
"code": "2222",
"priority": {
"p": "C"
}
}
]
}
highest_prio_ind = np.argmin([x['priority']['p'] for x in json['parent']])
print(json['parent'][highest_prio_ind]['code'])
which returns the wanted 999.

You can use Python's builtin function min() (doc) with custom key=:
json_data = {
"parent": [
{
"code": "333",
"priority": {
"p": "B"
}
},
{
"code": "999",
"priority": {
"p": "A"
}
},
{
"code": "2222",
"priority": {
"p": "C"
}
}
]
}
item = min(json_data['parent'], key=lambda k: k['priority']['p'])
print(item['code'])
Prints:
999

Let's just take your JSON Object as a variable and sort it.
parent = [
{
"code": "333",
"priority": {
"p": "B"
}
},
{
"code": "999",
"priority": {
"p": "A"
}
},
{
"code": "2222",
"priority": {
"p": "C"
}
}
]
To parse and sort the same there is a simple solution of lambda function.
parent = sorted(parent, key=lambda k: k['priority'].get('p', 0), reverse=False)
This will give you output something like this..
{'code': '999', 'priority': {'p': 'A'}}
{'code': '333', 'priority': {'p': 'B'}}
{'code': '2222', 'priority': {'p': 'C'}}
You can even turn into reverse by just doing reverse=True.
To get the value directly just find the code value of first element.
print(parent[0]['code'])
This will give you 999

Related

Update dictionary with nested dictionary

I have this json file used to list material by ref -> color and size:
{
"base": {
"ref": {
"3021000": {
"color": {
"bleu azur": {
"size": {
"01": "3021000-80300-01",
"13": "3021000-80300-13",
"12": "3021000-80300-12",
"36": "3021000-80300-36"
}
}
}
}
},
"customer_ref": {}
}
}
With a program I will load the json as a dict and search the dict to try and find the full ref corresponding to the value of a size (the full ref for the material 3021000 bleu azur 01 is 3021000-80300-01
It's working like a charm, but now, if I have a material with: ref=3021000, color=blanc and size=01, it doesn't exist in the dict, so I would like to insert the missing key - value: {"blanc": {"size": {"01": "corresponding full ref"}}}
I tried this:
ref = "3021000"
color = "blanc"
size = "01"
full_ref = "corresponding full ref"
missing_data = {ref: {"color": {color: {"size": {size: full_ref}}}}}
data["base"]["ref"] = missing_data
but it overwrite the dictionary; what I would like is to update the dict, not overwrite it.
How about this?
import json
d = {
"base": {
"ref": {
"3021000": {
"color": {
"bleu azur": {
"size": {
"01": "3021000-80300-01",
"13": "3021000-80300-13",
"12": "3021000-80300-12",
"36": "3021000-80300-36"
}
}
}
}
},
"customer_ref": {}
}
}
ref = "3021000"
color = "blanc"
size = "01"
full_ref = "corresponding full ref"
missing_data = {color: {"size": {size: full_ref}}}
d["base"]["ref"][ref]["color"].update(missing_data)
print(json.dumps(d, indent=2))
Output:
{
"base": {
"ref": {
"3021000": {
"color": {
"bleu azur": {
"size": {
"01": "3021000-80300-01",
"13": "3021000-80300-13",
"12": "3021000-80300-12",
"36": "3021000-80300-36"
}
},
"blanc": {
"size": {
"01": "corresponding full ref"
}
}
}
}
},
"customer_ref": {}
}
}

Remove keys but keep values from dictionary

Let's say I have this dictionary:
{
"id": "132-sd-sa-23-a-1",
"data": {
"lastUpdated": { "S": "2020-07-22T21:39:20Z" },
"profile": {
"M": {
"address": { "L": [] },
"fakeField": { "S": "someValue" },
"someKey": { "M": { "firstName": { "S": "Test" } } }
}
},
"groups": {
"L": [{ "S": "hello world!" }]
}
}
}
How can I remove the "M", "S", "L", etc. keys from the dictionary but keep the values. So it would turn into this:
{
"id": "132-sd-sa-23-a-1",
"data": {
"lastUpdated": "2020-07-22T21:39:20Z",
"profile": {
"address": [],
"fakeField": "someValue",
"someKey": { "firstName": "Test" }
},
"groups": ["hello world!"]
}
}
I could turn the dictionary into a string, loop through it, and remove what's necessary but that doesn't seem efficient or fast. I can't save the original list as the output that I'm hoping for initially so I need to convert it myself.
Sounds like a job for recursion:
def unsml(obj):
if isinstance(obj, dict):
if len(obj) == 1:
(key, value), *_ = obj.items() # get the only key and value
if key in "SML":
return unsml(value)
return {
key: unsml(value) if isinstance(value, dict) else value
for key, value
in obj.items()
}
elif isinstance(obj, list):
return [unsml(value) for value in obj]
return obj
Then just do new_dict = unsml(old_dict).

Python and JSON - if Key matches Move value from a key to root key

I have an application which generates clickstream data and pushes the data into a JSON. Almost 1000 clicks data will be saved in that file.
File contents: (steam-00001.json)
{
"date": {
"s": "2019-04-20"
},
"name": {
"s": "www.mywebsite.com"
},
"products": {
"m": {
"13128": {
"m": {
"quantity": {
"s": "1"
},
"price": {
"n": "799"
}
}
}
}
}
}
{
"date": {
"s": "2019-04-20"
},
"name": {
"s": "www.mywebsite.com"
},
"products": {
"m": {
"13128": {
"m": {
"quantity": {
"s": "1"
},
"price": {
"n": "799"
}
}
}
}
}
}
If you see the above JSON file, all of my values are pointed with s,m,n. The developers used this for some reference.
S - Single value
M - Multiple value
N - Number
Now I need to remove these references. I tried multiple json load and dumps but not able to achieve what im expecting.
Could someone help me on this?
Expected Output:
{
"date": "2019-04-20",
"name": "www.mywebsite.com",
"products": {
"13128": {
"quantity": "1",
"price": "799"
}
}
}
{
"date": "2019-04-20",
"name": "www.mywebsite.com",
"products": {
"13128": {
"quantity": "1",
"price": "799"
}
}
}
Steps I tried:
import json
def load_json_multiple(segments):
chunk = ""
for segment in segments:
chunk += segment
try:
yield json.loads(chunk)
chunk = ""
except ValueError:
pass
def filterJson(payload):
for key, value in payload.items():
if isinstance(value, dict):
for key1 in value.keys():
if(key1 == "M"):
payload[key] = value["M"]
tmp = filterJson(value)
if(tmp != None):
payload[key] = tmp
#print ans
else:
if(key == "S" or key == "N"):
return payload.pop(key)
with open('/home/ec2-user/olddata', 'r') as f:
for parsed_json in load_json_multiple(f):
print parsed_json
filterJson(parsed_json)
print parsed_json

Python - create dynamic nested dictionary from list of dictionary

Below is sample list data, I want to convert it into a dynamic dictionary.
result = [
{
"standard": "119",
"score": "0",
"type": "assignment",
"student": "4"
},
{
"standard": "119",
"score": "0",
"type": "assignment",
"student": "5"
},
{
"standard": "118",
"score": "0",
"type": "assessment",
"student": "4"
}
]
I want to create one function conv_to_nested_dict(*args,data), which convertes all list of key to dictonary dynamically.
For example : conv_to_nested_dict(['standard','student'],result) should give op :
{
"118": {
"4": [{
"score": "0",
"type": "assessment"
}]
},
"119": {
"4": [{
"score": "0",
"type": "assignment"
}],
"5": [{
"score": "0",
"type": "assignment"
}]
}
}
conv_to_nested_dict(['standard','type'],result)
{
"118": {
"assessment": [{
"score": 0,
"student": "4"
}]
},
"119": {
"assignment": [{
"score": 0,
"student": "4"
},{
"score": 0,
"student": "5"
}]
}
}
This is a general idea.
def conf_to_nested_dict(keys, result):
R = {}
for record in result:
node = R
for key in keys[:-1]:
kv = record[key]
next_node = node.get(kv, {})
node[kv] = next_node
node = next_node
last_node = node.get(record[keys[-1]], [])
last_node.append(record)
node[record[keys[-1]]] = last_node
return R
#R is your structure
result is your source array, keys are the keys by which you want to group results. Iterate over results, for each record - create a tree structure based on key values ( record[key] ). For the last key - create a list and append the record to it.

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"}}]

Categories