Removing JSON property in array of objects - python

I have a JSON array that I'm cleaning up in Python. I want to remove the imageData property:
data.json
[{"title": "foo", "imageData": "xyz123"},
{"title": "bar", "imageData": "abc123"},
{"title": "baz", "imageData": "def456"}]
I am setting up a list comprehension to remove the property, but I'm not sure how to create the variable that focuses on imageData:
import json
with open('data.json') as json_data:
data = json.load(json_data)
clean_data = [ item for item in data if not item['imageData'] ]
# Write `clean_data` to new json file
When I print the list comprehension, it returns an empty array. What do I have to correct to get this working properly?

An easy solution to your problem is deleting the unwanted key in place, with del:
import json
with open('data.json') as json_data:
data = json.load(json_data)
for element in data:
del element['imageData']
You should add some safety checks, but you get the idea.

If not all the elements have an imageData key, then using del will cause an KeyError exception. You could guard against that by using pop with a default:
for item in data:
item.pop('image', None)

[ item for item in data if not item['imageData'] ]
is empty becaus all have imageData. You are just testing for it, not removing it.
Loop over date and del item['imageData'] on each item.

How about:
clean_data = [k:v for k,v in data.iteritems() if k != 'imageData']
Or a dictionary expresion/comprehension if you want a dictionary:
clean_data = {k:v for k,v in data.iteritems() if k != 'imageData'}

Related

Iterating through a json in python - only wanting the value for one key in multiple dicts

I have this Json file, and I want to get the "navn" out with a iterating.
I need it to print:
Traktor
Bil and nothing else, how do I do that ?
[
{"navn": "Traktor", "år": 10, "købspris": 10000},
{"navn": "Bil", "år": 20, "købspris": 100000},
{},
{}
]
So far I have this idea
I know I need to import json file, and iterating through it but every time it gives me a error... I have tried searching the whole wide web and nothing came up
my code so far:
import json
def main():
f = open("/Users/maltheschroderjakobsen/Desktop/coding/test/mat.json",)
f = json.load(f)
for key in f["navn"]:
print (key)
main()
But every time I try anything else it gives me a error
f seems to be a list, not a dictionary:
for dct in f:
if "navn" in dct: # the elements are dicts!
print(dct["navn"])
It's because some dicts have no key navn. Use dict.get instead:
import json
def main():
file = open("/Users/maltheschroderjakobsen/Desktop/coding/test/mat.json",)
data = json.load(file)
for dct in data:
print(dct.get("navn", ""))
main()
So long as the JSON only has dicts, you can do:
js='''\
[
{"navn": "Traktor", "år": 10, "købspris": 10000},
{"navn": "Bil", "år": 20, "købspris": 100000},
{},
{}
]'''
import json
>>> [e['navn'] for e in json.loads(js) if e.get('navn', '')]
['Traktor', 'Bil']
JSON can also have other datatypes such as lists or numeral. If there is a possibility of something other than a dict in the JSON, you can do:
[e['navn'] for e in json.loads(js) if isinstance(e, dict) and e.get('navn', '')]

How to append the list of dictionary to same list in python?

I'm having a JSON with nested values. I need to remove the key of the nested field and need to keep the values as plain JSON.
JSON(Structure of my JSON)
[
{
"id":"101",
"name":"User1",
"place":{
"city":"City1",
"district":"District1",
"state":"State1",
"country":"Country1"
},
"access":[{"status":"available"}]
}
]
I need to get the JSON output as:
Expected Output:
[
{
"id":"101",
"name":"User1",
"city":"City1",
"district":"District1",
"state":"State1",
"country":"Country1"
"access":[{"status":"available"}]
}
]
What i need is:
I need to parse the JSON
Get the Placefield out of the JSON
Remove the key and brackets and append the values to existing
Python
for i in range(0,len(json_data)):
place_data = json_data[i]['place']
print(type(place_data)) #dict
del place_data['place']
Any approach to get the expected output in python.?
One way to accomplish this could be by
for i in json_data:
i.update(i.pop("place"))
Another way to accomplish this with multiple "keys" updated...
This would only work for a single nested level as described in the original question
def expand(array):
flatten = list()
for obj in array:
temp = {}
for key, value in obj.items():
if isinstance(value, dict):
temp.update(value)
else:
temp.update({key:value})
flatten.append(temp)
return flatten

Python remove from json dict doesn't work

When i call this function to remove an item from a dict imported from json it doesn't work
def removeKey(key):
with open ("keys.json") as f:
data = json.loads(f.read())
for d in data["keys"]:
if(d["key"] == key):
del d
print(data)
with open ("keys.json", "w") as f:
json.dump(data, f)
This is how the dict is set up in JSON
{"keys": [
{"key": 1599853953652, "role": "MODERATOR", "Server": 753230650181550141, "uses": 1, "maxuses": 0}
]
}
It seems like you actually want to remove any dictionaries in the list of dicts under "keys" if the value of their "key" entry matches a certain number (e.g. 1599853953652).
Assuming that's the case, the cleanest approach is actually to create a new list that filters out the unwanted entries; you can't simply call del to remove an element while iterating.
data = json.loads(f.read())
filtered_keys = [d for d in data["keys"] if d["key"] != key]
data["keys"] = filtered_keys
remove 'role' - one liner demo
data = {"keys": [
{"key": 1599853953652, "role": "MODERATOR", "Server": 753230650181550141, "uses": 1, "maxuses": 0}
]
}
data['keys'][0].pop('role',None)
print(data)
output
{'keys': [{'key': 1599853953652, 'Server': 753230650181550141, 'uses': 1, 'maxuses': 0}]}
Using del d only deletes the variable d but doesn't affect the list you want to remove from. You need operate on the list itself. I would use the pop() method, although del would work too.
def removeKey(key):
with open ("keys.json") as f:
data = json.loads(f.read())
for i, d in enumerate(data["keys"]):
if d["key"] == key:
data["keys"].pop(i)
print(data)
with open ("keys.json", "w") as f:
json.dump(data, f)
for d in data["keys"]:
if(d["key"] == key):
del d
del deletes names. Deleting a name does not delete the associated value, unless it was the only name for the value.
The for d in ... loop creates d as an additional name for data["keys"]["key"]. When you del d, you are only deleting the name d -- you are not deleting the value from data.
This is equivalent to:
x = 1
y = x
del y
After running this code, x still exists. del y just removed the name y.
To put it another way, think of post-it notes stuck onto boxes. The post-it notes are names, and the boxes are values. One box can have many notes stuck on it, and removing a note doesn't destroy the box (unless it was the only note).

Remove entire JSON object if it contains a specified phrase (from a list in python)

Have a JSON file output similar to:
{
"object1": {
"json_data": "{json data information}",
"tables_data": "TABLES_DATA"
},
"object2": {
"json_data": {json data information}",
"tables_data": ""
}
}
Essentially, if there is an empty string for tables_data as shown in object2 (eg. "tables_data": ""), I want the entire object to be removed so that the output would look like:
{
"object1": {
"json_data": "{json data information}",
"tables_data": "TABLES_DATA"
}
}
What is the best way to go about doing this? Each of these objects correspond to a separate index in a list that I've appended called summary[].
To achieve this, you could iterate through the JSON dictionary and test the tables_data values, adding the objectX elements to a new dictionary if their tables_data value passes the test:
new_dict = {k: v for k, v in json_dict.items()
if v.get("tables_data", "") != ""}
If your JSON objectX is stored in a list as you say, these could be processed as follows using a list comprehension:
filtered_summary = [object_dict for object_dict in summary
if object_dict.get("tables_data", "") != ""]
Unless you have compelling reasons to do otherwise, the pythonic way to filter out a list or dict (or any iterable) is not to change it in place but to create a new filtered one. For your case this would look like
raw_data = YOUR_DICT_HERE_WHEREVER_IT_COMES_FROM
# NB : empty string have a false value in a boolean test
cleaned_data = {k:v for k, v in raw_data.items() if not v["table_data"]}

How do I iterate through nested dictionaries in a list of dictionaries?

Still new to Python and need a little help here. I've found some answers for iterating through a list of dictionaries but not for nested dictionaries in a list of dictionaries.
Here is the a rough structure of a single dictionary within the dictionary list
[{ 'a':'1',
'b':'2',
'c':'3',
'd':{ 'ab':'12',
'cd':'34',
'ef':'56'},
'e':'4',
'f':'etc...'
}]
dict_list = [{ 'a':'1', 'b':'2', 'c':'3', 'd':{ 'ab':'12','cd':'34', 'ef':'56'}, 'e':'4', 'f':'etc...'}, { 'a':'2', 'b':'3', 'c':'4', 'd':{ 'ab':'23','cd':'45', 'ef':'67'}, 'e':'5', 'f':'etcx2...'},{},........,{}]
That's more or less what I am looking at although there are some keys with lists as values instead of a dictionary but I don't think I need to worry about them right now although code that would catch those would be great.
Here is what I have so far which does a great job of iterating through the json and returning all the values for each 'high level' key.
import ujson as json
with open('test.json', 'r') as f:
json_text = f.read()
dict_list = json.loads(json_text)
for dic in dict_list:
for val in dic.values():
print(val)
Here is the first set of values that are returned when that loop runs
1
2
3
{'ab':'12','cd':'34','ef':'56'}
4
etc...
What I need to be able to do pick specific values from the top level and go one level deeper and grab specific values in that nested dictionary and append them to a list(s). I'm sure I am missing a simple solution. Maybe I'm looking at multiple loops?
Following the ducktype style encouraged with Python, just guess everything has a .values member, and catch it if they do not:
import ujson as json
with open('test.json', 'r') as f:
json_text = f.read()
dict_list = json.loads(json_text)
for dic in dict_list:
for val in dic.values():
try:
for l2_val in val.values():
print(l2_val)
except AttributeError:
print(val)
Bazingaa's solution would be faster if inner dictionaries are expected to be rare.
Of course, any more "deep" and you would need some recursion probably:
def print_dict(d):
for val in d.values():
try:
print_dict(val)
except AttributeError:
print(val)
How about checking for the instance type using isinstance (of course only works for one level deeper). Might not be the best way though
for dic in dict_list:
for val in dic.values():
if not isinstance(val, dict):
print(val)
else:
for val2 in val.values():
print (val2)
# 1
# 2
# 3
# 12
# 34
# 56
# 4
# etc...
# 2
# 3

Categories