Store two values from JSON_file in new dictionary with python - python

I want to store two values from JSON_file in new dict like this : {[1,2,5]:[0], [1,2,4]:[2]}
my JSON-file looks like this :
{
"index": [
{
"timestamp": "2018-04-17 17:56:25",
"src": "src",
"dst": [1,2,5],
"value": [0],
"datatype": "datatype"
},
{
"timestamp": "2018-04-17 18:00:43",
"src": "src",
"dst": [1,2,4],
"value": [2],
"datatype": "datatype"
}
]
}
I wrote this code:
with open(filename) as feedjson:
json_data = json.load(feedjson)
feedjson.close()
list_dev = {}
for i in json_data["index"]:
key = i['value']
value = i['dst']
list_dev[key] = value
print(list_dev)
I get this error:
list_dev.update({key: value})
TypeError: unhashable type: 'list'
can someone help me to fix this problem please?

This is just for understanding purposes:
Dictionary keys should be immutable as explained here. In the question, [1,2,5] is a list which are mutable(contents can be modified with methods like append,pop, push) data types. So, the only way to use the entire contents of a list as a dictionary key(highly unusual) is to convert it to an immutable data type such as a tuple or string:
new_dict = {} #initialize empty dictionary
dst = t['index'][0]['dst'] #[1,2,5]
value = t['index'][0]['value'] #[0]
new_dict[tuple(dst)] = value #new_dict key "dst" as tuple
print(new_dict)
--->{(1, 2, 5): [0]}
new_dict[str(dst)] = value #new_dict key "dst" as string
print(new_dict)
---->{'[1, 2, 5]': [0]}

value is a list -> [1] or [2] or whatever, list is mutable object so you can't hash it
you can use the element in the list like
key=i['value'][0]
or convert the list to tuple like
key=tuple(i['value'])
both objects are immutable thus can be hashed and used as a key
by the way with provide context manager so you don't need to close the file using feedjson.close(), with will do it for you

Related

How to remove an item from every dict in a list

Sample:
sample = {
"value1": "foo",
"value2": "bar",
"value3": "baz",
"array": [
{
"key1":'value1',
"key2":'value2',
"key3":'value3',
},
{
"key1":'value4',
"key2":'value5',
"key3":'value6',
},
{
"key1":'value7',
"key2":'value8',
"key3":'value9',
}
]
}
I need to delete all key1s and values from all dicts in this array leaving only key2, key3 in each object.
The only thing I can find from google is how to iterate and delete an entire dict in an list, not a single key.
Haven't tried deleting but I did just try to get the other values like this.. couldn't get this either
domains_list = dict(map(lambda item: (item['key1'], item['key2']), sample['array'].items()))
error: AttributeError: 'list' object has no attribute 'items'
To get You moving: sample['array'] is a list (python type), which doesnt have .items(). So I'd iterate something like for dictionary in sample['array'] and then call dictionary.items().

Python - remove json object if missing key

I'm looking to delete all objects from some JSON data if it is missing the key or value.
Here is a snippet of the JSON data:
[
{
"cacheId": "eO8MDieauGIJ",
"pagemap": {}
},
{
"cacheId": "AWYYu9XQnuwJ",
"pagemap": {
"cse_image": [
{
"src": "https://someimage.png"
}
]
}
},
{
"cacheId": "AWYYu9XQnuwJ",
"pagemap": {
"cse_image": [
{
}
]
}
}
]
I'm looking to delete the 1st and 3rd object in the data because the 1st object has an empty ['pagemap'] and the 3rd object has an empty ['pagemap']['cse_image']
Here is what I've tried so far without any luck:
for result in data[:]:
if result['pagemap']['cse_image'] == []:
data.remove(result)
for result in data[:]:
if result['pagemap'] == None:
data.remove(result)
for result in data[:]:
if len(result['pagemap']) == 0:
data.remove(result)
Thanks for the help!
Two things:
You don't want to remove elements from a list while iterating over them -- the memory you're removing is shifting as you're accessing it.
The third object has a nonempty ['pagemap']['cse_image']. Its value is a one-element list containing an empty dictionary. You need to index into the list to check whether or not the inner dictionary is empty.
With these two points in mind, here is an approach using filter() that also leverages the fact that empty data structures have falsy values:
result = list(filter(lambda x: x['pagemap'] and x['pagemap']['cse_image'] and x['pagemap']['cse_image'][0], data))
print(result)
If that data structure remains consistent, you can do it with a list comprehension.
[e for e in d if e["pagemap"] and e["pagemap"]["cse_image"] and any(e["pagemap"]["cse_image"])]
produces:
[{'cacheId': 'AWYYu9XQnuwJ', 'pagemap': {'cse_image': [{'src': 'https://someimage.png'}]}}]
Where d is your given data structure.

Update dicitonary key with every value from a list

Given this list:
pc = ['OferteConfigurabile_S2D_Rate',
'OferteConfigurabile_S2D_Rate_si_Discount',
'OferteConfigurabile_S2D_SimOnly_si_Discount',
'OferteConfigurabile_S2D_SimOnly',
'OferteConfigurabile_S2D_VMM_Rate']
And this dictionary:
lst = []
dataModel = {
'channel': 'RETAIL',
'searchType': 'MSISDN',
'searchValue': 727277696,
'configType': 'RETENTIE',
'scenarioName_PC': 'OferteConfigurabile_ServiceOnly',
'retention_option': '360_OFERTE_MOBILE',
'retention_flow': 'ConfigureazaOferte',
}
I want for every element in the 'pc' list to update dateModel['scenarioName_PC'] and store the resulting dictionary into a list but slightly changed by creating a new dict with a custom key and dataModel dictionary as its value
for i in pc:
dataModel['scenarioName_PC'] = i
lst.append({f"{dataModel['retention_option']}_{dataModel['retention_flow']}_{i}" : dataModel})
print(lst)
The problem is that when i print the list 'scenarioName_PC' key always has the last element from the iterated list, the dataModel dictionary dosen't save the value for every for loop iteration, it somehow only stores the last value in PC list
[
{
"360_OFERTE_MOBILE_ConfigureazaOferte_OferteConfigurabile_S2D_Rate":{
"channel":"RETAIL",
"searchType":"MSISDN",
"searchValue":727277696,
"configType":"RETENTIE",
"scenarioName_PC":"OferteConfigurabile_S2D_VMM_Rate",
"retention_option":"360_OFERTE_MOBILE",
"retention_flow":"ConfigureazaOferte"
}
},
{
"360_OFERTE_MOBILE_ConfigureazaOferte_OferteConfigurabile_S2D_Rate_si_Discount":{
"channel":"RETAIL",
"searchType":"MSISDN",
"searchValue":727277696,
"configType":"RETENTIE",
"scenarioName_PC":"OferteConfigurabile_S2D_VMM_Rate",
"retention_option":"360_OFERTE_MOBILE",
"retention_flow":"ConfigureazaOferte"
}
},
Expected result is a list with dataModel dictionary but for scenarioname_PC key to have every time 'i' as value.
[
{
"360_OFERTE_MOBILE_ConfigureazaOferte_OferteConfigurabile_S2D_Rate":{
"channel":"RETAIL",
"searchType":"MSISDN",
"searchValue":727277696,
"configType":"RETENTIE",
"scenarioName_PC":"OferteConfigurabile_S2D_Rate",
"retention_option":"360_OFERTE_MOBILE",
"retention_flow":"ConfigureazaOferte"
}
},
{
"360_OFERTE_MOBILE_ConfigureazaOferte_OferteConfigurabile_S2D_Rate_si_Discount":{
"channel":"RETAIL",
"searchType":"MSISDN",
"searchValue":727277696,
"configType":"RETENTIE",
"scenarioName_PC":"OferteConfigurabile_S2D_Rate_si_Discount",
"retention_option":"360_OFERTE_MOBILE",
"retention_flow":"ConfigureazaOferte"
}
},
while appending copy the dictionary object instead of just passing the dictionary. You are passing the dictionary reference which is being modified.
This should work.
import copy
for i in pc:
new_dataMode = copy.deepcopy(dataMode)
new_dataModel['scenarioName_PC'] = i
lst.append({f"{new_dataModel['retention_option']}_{new_dataModel['retention_flow']}_{i}" : new_dataModel})
print(lst)

creating nested json objects from a list

I am attempting to understand how to take a list and convert that into a nested JSON object.
Expected Output
{
"Name1": [
{
"key": "value",
"key": "value",
"key": "value",
"key": "value"
}
],
}
So far my thinking as gone as follows, convert the list to dictionary using comprehension and splitting key value pairs.
list1 = ['key value', 'key value', 'key value']
dict1 = dict(item.split(" ") for item in list1)
I then thought converting that into a JSON object would be something similar to:
print json.loads(dict1)
However, Im not sure how to create the "Name1" parent key. And it seems google is being particularly helpful. Im sure there is something simple im missing, any pointers would be appreacited.
EDIT
Included a list for reference
You simply put them in another dictionary, and use a new list. So:
import json
list1 = ['key1 value1', 'key2 value2', 'key3 value3']
dict1 = {'Name1': [dict(item.split(" ",1) for item in list1)] }
# ^ dict ^ list with 1 element end list ^ ^ end dict
json.dumps(dict1)
And this produces:
>>> print(json.dumps(dict1))
{"Name1": [{"key2": "value2", "key3": "value3", "key1": "value1"}]}
Notes:
A dictionary can only contain different keys (both in JSON and Python);
You better split with .split(" ",1) since if the value contains spaces, these are all seen as still a single value.
dictionaries are unordered, so the order of th keys can be shuffled.

For each loop with JSON object python

Alright, so I'm struggling a little bit with trying to parse my JSON object.
My aim is to grab the certain JSON key and return it's value.
JSON File
{
"files": {
"resources": [
{
"name": "filename",
"hash": "0x001"
},
{
"name": "filename2",
"hash": "0x002"
}
]
}
}
I've developed a function which allows me to parse the JSON code above
Function
def parsePatcher():
url = '{0}/{1}'.format(downloadServer, patcherName)
patch = urllib2.urlopen(url)
data = json.loads(patch.read())
patch.close()
return data
Okay so now I would like to do a foreach statement which prints out each name and hash inside the "resources": [] object.
Foreach statement
for name, hash in patcher["files"]["resources"]:
print name
print hash
But it only prints out "name" and "hash" not "filename" and "0x001"
Am I doing something incorrect here?
By using name, hash as the for loop target, you are unpacking the dictionary:
>>> d = {"name": "filename", "hash": "0x001"}
>>> name, hash = d
>>> name
'name'
>>> hash
'hash'
This happens because iteration over a dictionary only produces the keys:
>>> list(d)
['name', 'hash']
and unpacking uses iteration to produce the values to be assigned to the target names.
That that worked at all is subject to random events even, on Python 3.3 and newer with hash randomisation enabled by default, the order of those two keys could equally be reversed.
Just use one name to assign the dictionary to, and use subscription on that dictionary:
for resource in patcher["files"]["resources"]:
print resource['name']
print resource['hash']
So what you intend to do is :
for dic in x["files"]["resources"]:
print dic['name'],dic['hash']
You need to iterate on those dictionaries in that array resources.
The problem seems to be you have a list of dictionaries, first get each element of the list, and then ask the element (which is the dictionary) for the values for keys name and hash
EDIT: this is tested and works
mydict = {"files": { "resources": [{ "name": "filename", "hash": "0x001"},{ "name": "filename2", "hash": "0x002"}]} }
for element in mydict["files"]["resources"]:
for d in element:
print d, element[d]
If in case you have multiple files and multiple resources inside it. This generalized solution works.
for keys in patcher:
for indices in patcher[keys].keys():
print(patcher[keys][indices])
Checked output from myside
for keys in patcher:
... for indices in patcher[keys].keys():
... print(patcher[keys][indices])
...
[{'hash': '0x001', 'name': 'filename'}, {'hash': '0x002', 'name': 'filename2'}]

Categories