I need to get the 'ids' of this json response,the thing is that, there are many dictionaries with a list of dictionaries inside,how can I do this??(PS:len(items) is 20,so I need to get the 20 ids in the form of a dictionary.
{'playlists': {'href': 'https://api.spotify.com/v1/search?query=rewind-The%25&type=playlist&offset=0&limit=20',
'items': [{'collaborative': False,
'description': 'Remember what you listened to in 2010? Rewind and rediscover your favorites.',
'external_urls': {'spotify': 'https://open.spotify.com/playlist/37i9dQZF1DXc6IFF23C9jj'},
'href': 'https://api.spotify.com/v1/playlists/37i9dQZF1DXc6IFF23C9jj',
'id': '37i9dQZF1DXc6IFF23C9jj',
'images': [{'height': None,
'url': 'https://i.scdn.co/image/ab67706f0000000327ba1078080355421d1a49e2',
'width': None}],
'name': 'Rewind - The Sound of 2010',
'owner': {'display_name': 'Spotify',
'external_urls': {'spotify': 'https://open.spotify.com/user/spotify'},
'href': 'https://api.spotify.com/v1/users/spotify',
'id': 'spotify',
'type': 'user',
'uri': 'spotify:user:spotify'},
'primary_color': None,
'public': None,
'snapshot_id': 'MTU5NTUzMTE1OSwwMDAwMDAwMGQ0MWQ4Y2Q5OGYwMGIyMDRlOTgwMDk5OGVjZjg0Mjdl',
'tracks': {'href': 'https://api.spotify.com/v1/playlists/37i9dQZF1DXc6IFF23C9jj/tracks',
'total': 100},
'type': 'playlist',
'uri': 'spotify:playlist:37i9dQZF1DXc6IFF23C9jj'},
Im trying to get it through this:
dict={'id':''}
for playlists in playlist_data['playlists']:
for items in playlists['items']:
for item in items:
for dic in range(len(item)):
for id in dic['id']:
dict.update('id')
print(dict)
I get this error:
TypeError: string indices must be integers ```
Try something like this:
ids = [item["id"] for item in json_data["playlists"]["items"]]
This is called a list comprehension.
You want to iterate over all of the "items" within the "playlists" key.
You can access that list of items:
json_data["playlists"]["items"]
Then you iterate over each item within items:
for item in json_data["playlists"]["items"]
Then you access the "id" of each item:
item["id"]
You can index an object using the keys of object. I can see there are two places where id is present in an object. To retrieve those two ids and store them in a dictionary format, you can use the following approach -
_json = {
'playlists': {
'href': 'https://api.spotify.com/v1/search?query=rewind-The%25&type=playlist&offset=0&limit=20',
'items': [{
'collaborative': False,
'description': 'Remember what you listened to in 2010? Rewind and rediscover your favorites.',
'external_urls': {
'spotify': 'https://open.spotify.com/playlist/37i9dQZF1DXc6IFF23C9jj'
},
'href': 'https://api.spotify.com/v1/playlists/37i9dQZF1DXc6IFF23C9jj',
'id': '37i9dQZF1DXc6IFF23C9jj',
'images': [{
'height': None,
'url': 'https://i.scdn.co/image/ab67706f0000000327ba1078080355421d1a49e2',
'width': None
}],
'name': 'Rewind - The Sound of 2010',
'owner': {
'display_name': 'Spotify',
'external_urls': {
'spotify': 'https://open.spotify.com/user/spotify'
},
'href': 'https://api.spotify.com/v1/users/spotify',
'id': 'spotify',
'type': 'user',
'uri': 'spotify:user:spotify'
},
'primary_color': None,
'public': None,
'snapshot_id': 'MTU5NTUzMTE1OSwwMDAwMDAwMGQ0MWQ4Y2Q5OGYwMGIyMDRlOTgwMDk5OGVjZjg0Mjdl',
'tracks': {
'href': 'https://api.spotify.com/v1/playlists/37i9dQZF1DXc6IFF23C9jj/tracks',
'total': 100
},
'type': 'playlist',
'uri': 'spotify:playlist:37i9dQZF1DXc6IFF23C9jj'
}, ]
}
}
res_dict = {'id':[items['id'], items['owner']['id']] for items in _json['playlists']['items']}
print(res_dict)
OUTPUT :
{'id': ['37i9dQZF1DXc6IFF23C9jj', 'spotify']}
If you don't need the second id that's present in the json object, you can just remove it from above res_dict and modify it as -
res_dict = {'id':items['id'] for items in _json['playlists']['items']}
This will only fetch the id present in the items array as key of any element and not any further nested ids (like items[i]->owner->id won't be in the final res as it was in the fist case ).
The original post is Go through json line by line including unkown nested arrays and objects
I am trying to search for a specific value in all nested lists and nested dictionaries inside a JSON dictionary. The structure of the dictionary is not always known. The nested dictionary can have a nested list.
The key I'm looking for is Date and should not have String. Example key = Date is True but if key = DateString condition is not met.
Code:
def ConvertTimestamp(my_list_of_dicts: list):
for e in my_list_of_dicts:
# check top level keys whose values are not a list
keys_with_date = [k for k, v in e.items() if 'Date' in k and type(v) and 'String' not in k != list]
for k1 in keys_with_date:
e[k1] = 'found'
# check top level keys whose values are a list
keys_with_lists = [k for k, v in e.items() if type(v) == list]
for k1 in keys_with_lists:
for i, d in enumerate(e[k1]):
for k2, v in d.items():
if 'Date' in k2 and 'String' not in k2:
e[k1][i][k2] = 'found'
return my_list_of_dicts
Data
test_data = [{
"PurchaseOrderID": "aaff50c2-05d5-4943-9a37-421d1b326dc3",
"PurchaseOrderNumber": "PO-0001",
"DateString": "2020-06-04T00:00:00",
"Date": "2020-06-04T02:00:00.000000",
"DeliveryDateString": "2020-06-11T00:00:00",
"DeliveryDate": "2020-06-11T02:00:00.000000",
"DeliveryAddress": "",
"AttentionTo": "",
"Telephone": "",
"DeliveryInstructions": "",
"HasErrors": false,
"IsDiscounted": true,
"Reference": "",
"Type": "PURCHASEORDER",
"CurrencyRate": 1.0,
"CurrencyCode": "EUR",
"Contact": {
"ContactID": "31dcd998-026662967",
"ContactStatus": "ACTIVE",
"Name": "Test",
"FirstName": "",
"LastName": "",
"Addresses": [],
"Phones": [],
"UpdatedDateUTC": "/Date(1591272554130+0000)/",
"ContactGroups": [],
"DefaultCurrency": "EUR",
"ContactPersons": [],
"HasValidationErrors": false
},
"BrandingThemeID": "86a1c878-7b2ed792b224",
"Status": "DELETED",
"LineAmountTypes": "Exclusive",
"SubTotal": 1000.0,
"TotalTax": 0.0,
"Total": 1000.0,
"UpdatedDateUTC": "2020-06-04T12:14:26.527000",
"HasAttachments": false }]
Result should be
[{
"PurchaseOrderID": "aaff50c2-05d5-4943-9a37-421d1b326dc3",
"PurchaseOrderNumber": "PO-0001",
"DateString": "2020-06-04T00:00:00",
"Date": "2020-06-04T02:00:00.000000",
"DeliveryDateString": "2020-06-11T00:00:00",
"DeliveryDate": "2020-06-11T02:00:00.000000",
"DeliveryAddress": "",
"AttentionTo": "",
"Telephone": "",
"DeliveryInstructions": "",
"HasErrors": false,
"IsDiscounted": true,
"Reference": "",
"Type": "PURCHASEORDER",
"CurrencyRate": 1.0,
"CurrencyCode": "EUR",
"Contact": {
"ContactID": "31dcd998-026662967",
"ContactStatus": "ACTIVE",
"Name": "Test",
"FirstName": "",
"LastName": "",
"Addresses": [],
"Phones": [],
"UpdatedDateUTC": "2020-06-03T09:55:30.000000",
"ContactGroups": [],
"DefaultCurrency": "EUR",
"ContactPersons": [],
"HasValidationErrors": false
},
"BrandingThemeID": "86a1c878-7b2ed792b224",
"Status": "DELETED",
"LineAmountTypes": "Exclusive",
"SubTotal": 1000.0,
"TotalTax": 0.0,
"Total": 1000.0,
"UpdatedDateUTC": "2020-06-04T12:14:26.527000",
"HasAttachments": false }]
Since you don't know what the structure of the dictionaries are, it could be under an arbitrary number of levels.
Also, the expected result didn't really show what you want to do with the dictionary once found, so I've just added those dictionaries to a list.
Recursion helps in such cases.
def search_dict(d, results):
for k,v in d.items():
if 'Date' in k and 'String' not in k:
# Do what you want with `d` here.
# Your "Result should be" didn't really explain the
# found part, but if it gets here it means you found it.
# Appended to results as we want to continue searching for more.
# Appending (k,v,d) where d is the dictionary containing
# this key and value, incase you wanted that too.
# Adjust this accordingly.
results.append((k,v,d))
if isinstance(v, dict):
search_dict(v, results)
if isinstance(v, list):
search_list(v, results)
def search_list(l, results):
for item in l:
if not isinstance(item, dict):
continue # don't care about things that aren't dictionaries
if isinstance(item, list):
search_list(item, results)
if isinstance(item, dict):
search_dict(item, results)
def ConvertTimestamp(my_list_of_dicts: list):
results = []
search_list(my_list_of_dicts, results)
return results
Here is how you can recurse through the object, making the updates.
For sake of generality, the recursive function takes two externally defined callables an addition to the object being recursed:
a "key tester" function that should take a key (string) and return a boolean, which is used to decide which keys are to have their values updated
a "replacer" function that should take a value and return the new value
from datetime import date
from pprint import pprint
from copy import deepcopy
import re
def do_replacements(obj, key_tester, replacer):
"""
recursing through the nested list/dict structure,
and wherever key_tester(key) yields True,
use replacer function to generate the new value
"""
if isinstance(obj, dict):
for k, v in obj.items():
if key_tester(k):
obj[k] = replacer(v)
else:
do_replacements(v, key_tester, replacer)
elif isinstance(obj, list):
for item in obj:
do_replacements(item, key_tester, replacer)
def fix_time(ts):
"""
replace the timestamp if it fits a particular pattern
(based on code in original question)
"""
pattern = '\(|\)'
if not re.search(pattern, ts):
return ts
format = '%Y-%m-%dT%H:%M:%S.%f'
ts_utc = re.split(pattern, ts)[1]
ts_utc = ts_utc[:ts_utc.find("+")]
return date.fromtimestamp(float(ts_utc)/1000).strftime(format)
test_data = [{'PurchaseOrderID': 'aaff50c2-05d5-4943-9a37-421d1b326dc3', 'PurchaseOrderNumber': 'PO-0001', 'DateString': '2020-06-04T00:00:00', 'Date': '2020-06-04T02:00:00.000000', 'DeliveryDateString': '2020-06-11T00:00:00', 'DeliveryDate': '2020-06-11T02:00:00.000000', 'DeliveryAddress': '', 'AttentionTo': '', 'Telephone': '', 'DeliveryInstructions': '', 'HasErrors': False, 'IsDiscounted': True, 'Reference': '', 'Type': 'PURCHASEORDER', 'CurrencyRate': 1.0, 'CurrencyCode': 'EUR', 'Contact': {'ContactID': '31dcd998-026662967', 'ContactStatus': 'ACTIVE', 'Name': 'Test', 'FirstName': '', 'LastName': '', 'Addresses': [], 'Phones': [], 'UpdatedDateUTC': '/Date(1591272554130+0000)/', 'ContactGroups': [], 'DefaultCurrency': 'EUR', 'ContactPersons': [], 'HasValidationErrors': False}, 'BrandingThemeID': '86a1c878-7b2ed792b224', 'Status': 'DELETED', 'LineAmountTypes': 'Exclusive', 'SubTotal': 1000.0, 'TotalTax': 0.0, 'Total': 1000.0, 'UpdatedDateUTC': '2020-06-04T12:14:26.527000', 'HasAttachments': False}]
func = lambda k: "Date" in k and "String" not in k
output = deepcopy(test_data)
do_replacements(output, func, fix_time)
pprint(output)
gives:
[{'AttentionTo': '',
'BrandingThemeID': '86a1c878-7b2ed792b224',
'Contact': {'Addresses': [],
'ContactGroups': [],
'ContactID': '31dcd998-026662967',
'ContactPersons': [],
'ContactStatus': 'ACTIVE',
'DefaultCurrency': 'EUR',
'FirstName': '',
'HasValidationErrors': False,
'LastName': '',
'Name': 'Test',
'Phones': [],
'UpdatedDateUTC': '2020-06-04T00:00:00.000000'},
'CurrencyCode': 'EUR',
'CurrencyRate': 1.0,
'Date': '2020-06-04T02:00:00.000000',
'DateString': '2020-06-04T00:00:00',
'DeliveryAddress': '',
'DeliveryDate': '2020-06-11T02:00:00.000000',
'DeliveryDateString': '2020-06-11T00:00:00',
'DeliveryInstructions': '',
'HasAttachments': False,
'HasErrors': False,
'IsDiscounted': True,
'LineAmountTypes': 'Exclusive',
'PurchaseOrderID': 'aaff50c2-05d5-4943-9a37-421d1b326dc3',
'PurchaseOrderNumber': 'PO-0001',
'Reference': '',
'Status': 'DELETED',
'SubTotal': 1000.0,
'Telephone': '',
'Total': 1000.0,
'TotalTax': 0.0,
'Type': 'PURCHASEORDER',
'UpdatedDateUTC': '2020-06-04T12:14:26.527000'}]
(Note: the output shown here is the pretty-printed python object, rather than JSON, although similar.)
I have been trying to do something simple yet something hard for me to solve it!
I have a json object that looks like:
jsonObject = {
'attributes': {
'192': { <--- This can be changed times to times meaning different number
'id': '192',
'code': 'hello',
'label': 'world',
'options': [
{
'id': '211',
'label': '5'
},
{
'id': '1202',
'label': '8.5'
},
{
'id': '54',
'label': '9'
},
{
'id': '1203',
'label': '9.5'
},
{
'id': '58',
'label': '10'
}
]
}
},
'template': '12345',
'basePrice': '51233',
'oldPrice': '51212',
'productId': 'hello',
}
and what I want to do is to get the values from options (To have both id and label saved into a list)
For now I only managed to do:
for att, value in jsonObject.items():
print(f"{att} - {value}"
How can I get the label and id?
You can try the following code:
attr = jsonObject['attributes']
temp = list(attr.values())[0] # It is same as "temp = attr['192']", but you said '192' can be changed.
options = temp['options']
for option in options:
print(f"id: {option['id']}, label: {option['label']}")
I am trying to merge two nested dictionaries that will merge different dictionaries by comparing values, If the key will be same it will be replaced with the recent value.
Im using always_merger.merge() for merging but is appending the different element.It supposed to compare and replace values with recent one.
dictionary_1 = dict([('modifyParameterReq', {
'managedObject': {
'distName': 'ethLink_1',
'operation': 'create_mo',
'parameter': [
{
'parameterName': 'houseName',
'newValue': 'Bhawan',
'prevValue': ''
},
{
'parameterName': 'subscribe',
'newValue': 'TRUE',
'prevValue': ''
},
{
'parameterName': 'remoteMacAddress',
'newValue': 'd6-68-05-5e-06-b9',
'prevValue': ''
}
],
'class': 'EthernetLink'
}
})]
)
dictionary_2 = dict([('modifyParameterReq', {
'managedObject': {
'distName': 'ethLink_1',
'operation': 'create_mo',
'parameter': [
{
'parameterName': 'subscribe',
'newValue': 'FALSE',
'prevValue': ''
},
{
'parameterName': 'remoteMacAddress',
'newValue': 'a1-b1-c3-d4-e5-f6',
'prevValue': ''
},
{
'parameterName': 'yourName',
'newValue': 'Vicky',
'prevValue': ''
}
],
'class': 'EthernetLink'
}
})
]
)
if the element is not present add the element else replace with new value.
Any help should be appreciated.
This should do it. I 've written some comments in between to make it more readable:
# Get all current parameter names from dictionary 1.
currentDictParameterNames = [elem['parameterName'] for elem in dictionary_1['modifyParameterReq']['managedObject']['parameter']]
# Iterate through parameters from dictionary 2.
for index, dictData in enumerate(dictionary_2['modifyParameterReq']['managedObject']['parameter']):
# If current key iterated from dictionary 2 exists in dictionary 1, update.
if dictData['parameterName'] in currentDictParameterNames:
# FInd the location of the parameter name in dictionary 1 and update.
for i in range(len(dictionary_1['modifyParameterReq']['managedObject']['parameter'])):
if dictionary_1['modifyParameterReq']['managedObject']['parameter'][i]['parameterName'] == dictData['parameterName']:
dictionary_1['modifyParameterReq']['managedObject']['parameter'][i]['prevValue'] = dictionary_1['modifyParameterReq']['managedObject']['parameter'][i]['newValue']
dictionary_1['modifyParameterReq']['managedObject']['parameter'][i]['newValue'] = dictData['newValue']
break
# Else create a new record.
else:
dictionary_1['modifyParameterReq']['managedObject']['parameter'].append(dictData)
print(dictionary_1)
The result should be:
{'modifyParameterReq': {'managedObject': {
'distName': 'ethLink_1',
'operation': 'create_mo',
'parameter': [
{'parameterName': 'houseName', 'newValue': 'Bhawan', 'prevValue': ''},
{'parameterName': 'subscribe', 'newValue': 'FALSE', 'prevValue': 'TRUE'},
{'parameterName': 'remoteMacAddress', 'newValue': 'a1-b1-c3-d4-e5-f6', 'prevValue': 'd6-68-05-5e-06-b9'},
{'parameterName': 'yourName', 'newValue': 'Vicky', 'prevValue': ''}],
'class': 'EthernetLink',
}}}
I am able to get a dictionary from my request function. Here's what I get:
{
'collaborative': False,
'external_urls': {
'spotify': 'http://open.spotify.com/user/dashrif/playlist/3LEoetnegEv2Q8jdmB8TER'
},
'href': 'https://api.spotify.com/v1/users/dashrif/playlists/3LEoetnegEv2Q8jdmB8TER',
'id': '3LEoetnegEv2Q8jdmB8TER',
'images': [{
'height': 640,
'url': 'https://mosaic.scdn.co/640/0cd0508f78c5e5f6e2b01b3009753083c7977270527f35929eff151f80bcabec17b2fb9383da342b32d7d3432ff965abb01f706ec2efc38282a11b45d088e352f19eebb53874fcdc4366ff4249da45fe',
'width': 640
},
{
'height': 300,
'url': 'https://mosaic.scdn.co/300/0cd0508f78c5e5f6e2b01b3009753083c7977270527f35929eff151f80bcabec17b2fb9383da342b32d7d3432ff965abb01f706ec2efc38282a11b45d088e352f19eebb53874fcdc4366ff4249da45fe',
'width': 300
},
{
'height': 60,
'url': 'https://mosaic.scdn.co/60/0cd0508f78c5e5f6e2b01b3009753083c7977270527f35929eff151f80bcabec17b2fb9383da342b32d7d3432ff965abb01f706ec2efc38282a11b45d088e352f19eebb53874fcdc4366ff4249da45fe',
'width': 60
}],
'name': 'Life Playlist Vol. I: The Fuck You Getting Hype For? You Still Broke',
'owner': {
'external_urls': {
'spotify': 'http://open.spotify.com/user/dashrif'
},
'href': 'https://api.spotify.com/v1/users/dashrif',
'id': 'dashrif',
'type': 'user',
'uri': 'spotify:user:dashrif'
},
'public': True,
'snapshot_id': 'PCG8b/CxCfaCjX0mmFMZ3T9NUsJC1sz5MVAXfQf3aefQhcAi4Zdm2k+3rySb/HLw',
'tracks': {
'href': 'https://api.spotify.com/v1/users/dashrif/playlists/3LEoetnegEv2Q8jdmB8TER/tracks',
'total': 63
},
'type': 'playlist',
'uri': 'spotify:user:dashrif:playlist:3LEoetnegEv2Q8jdmB8TER'
}
At least I hope this is a dictionary. Honestly at this point I've gotten so many errors I'm not too sure. Here's the code in question:
playlist_api_endpoint = "{}/playlists".format(profile_data["href"])
playlists_response = requests.get(playlist_api_endpoint,
headers=authorization_header)
playlist_data = json.loads(playlists_response.text)
display_arr = [profile_data] + playlist_data["items"]
return render_template("index.html",sorted_array=display_arr)
Basically I want to be able to filter out the last uri object and any other uri objects when adding new playlists. I've tried .items(), filtered dictionary, and a couple of other things I can't remember. If anyone has an idea of where I'm going wrong or how to to achieve my goal, I'd love some help. Thanks!