Accessing nested data in a JSON API response - python

I have the following JSON file from a API request:
'data': {
'0x6c3e3fb3e1066132ae54b1049c7f1ffb9c875404': {
'address': {
'balance': '39674870110714259',
'balance_usd': 90.9045327455033,
'call_count': 10,
'contract_code_hex': None,
'contract_created': None,
'contract_destroyed': None,
'fees_approximate': '31500129889285741',
'fees_usd': 72.17424235567398,
'first_seen_receiving': '2021-03-14 '
'00:58:46',
'first_seen_spending': '2021-03-14 '
'01:03:47',
'last_seen_receiving': '2021-03-14 '
'02:12:47',
'last_seen_spending': '2021-03-14 '
'02:30:59',
'nonce': None,
'received_approximate': '166671175000000000000',
'received_usd': 320779.4692,
'receiving_call_count': 4,
'spending_call_count': 6,
'spent_approximate': '166600000000000000000',
'spent_usd': 320642.4844,
'transaction_count': 10,
'type': 'account'
},
'calls': [{
'block_id': 12034014,
'index': '0',
'recipient': '0x57f41689847f8b0676a0ce8a7c5eb5fb78e79596',
'sender': '0x6c3e3fb3e1066132ae54b1049c7f1ffb9c875404',
'time': '2021-03-14 '
'02:30:59',
'transaction_hash': '0x777e01251d9c42df4269abcf3c72fd668653f68bf0d4716ef992e57c1bca641c',
'transferred': True,
'value': 2.29e+19,
'value_usd': 44073.9069
},
{
'block_id': 12034002,
'index': '0',
'recipient': '0xf582a0db4e787492921d0faee3e19f0e9edee261',
'sender': '0x6c3e3fb3e1066132ae54b1049c7f1ffb9c875404',
'time': '2021-03-14 '
'02:29:30',
'transaction_hash': '0xc70bdc0efd23bb303d27866806fde689b00fa6e1f8c61850d11e3684bad7d16c',
'transferred': True,
'value': 2.5e+19,
'value_usd': 48115.6189
}
]
}
}
What I would like to do is to access the "recipient" section of the calls section for each call.
I have tried it as following:
data=json_response['data']
calls=data['0x6c3e3fb3e1066132ae54b1049c7f1ffb9c875404']['calls']
for i in calls:
recipient=calls[2]['recipient']
print(recipient)
However this seems to always give the same recipient in the output
What am I doing wrong?

In your code you provided, you are not actually using the iterator i to access the calls, instead you are using calls[2] which will always get the same call each time.
Instead, use:
for i in calls:
recipient=i['recipient']
print(recipient)

Related

How can I use the batchupdate function of the google form api with python to modify the url and answers?

Here is an example of my form. How can I use python to modify the url and answer for the first question, as I am not familiar with using batchupdate?
I can use "get" to retrieve information from the form.
{'formId': '1q4pJMDtiLxQ2cjmLXxowqJ5VPfI68bUUo',
'info': {'title': 'PIXEL ', 'documentTitle': 'daily'},
'settings': {'quizSettings': {'isQuiz': True}},
'revisionId': '00000067',
'responderUri': 'https://docs.google.com/forms/d/e/1FAIpQLScap6ZdpOnWIyxWqZNXjlfWW9DgPe-Wv_CUtziWw/viewform',
'items': [{'itemId': '7c0ddb37', 'pageBreakItem': {}},
{'itemId': '2870b06c', 'videoItem': {'video': {'youtubeUri': 'www.youtube.com/watch?v=Lt5HqPvM-eI', 'properties': {'alignment': 'LEFT', 'width': 320}}}},
{'itemId': '381aedf6', 'questionGroupItem': {'questions': [{'questionId': '4d7f011e', 'required': True, 'rowQuestion': {'title': 'pick'}}], 'grid': {'columns': {'type': 'RADIO', 'options': [{'value': '1'}, {'value': '2'}, {'value': '3'}]}}}, 'title': 'pay'},
{'itemId': '0f9dc00b', 'title': 'number', 'questionItem': {'question': {'questionId': '39523976', 'required': True,
'grading': {'correctAnswers': {'answers': [{'value':'1115'}]}}, 'textQuestion': {}}}},
{'itemId': '0a12a42e', 'pageBreakItem': {}},
{'itemId': '19640fea', 'videoItem': {'video': {'youtubeUri': 'www.youtube.com/watch?v=Lt5HqPvM-eI', 'properties': {'alignment': 'LEFT', 'width': 320}}}},
{'itemId': '685ba545', 'questionGroupItem': {'questions': [{'questionId': '044f9f9b', 'required': True, 'rowQuestion': {'title': 'pick'}}], 'grid': {'columns': {'type': 'RADIO', 'options': [{'value': '1'}, {'value': '2'}, {'value': '3'}]}}}, 'title': 'pay'},
{'itemId': '6a9d1b88', 'title': 'number', 'questionItem': {'question': {'questionId': '2199beb0', 'required': True,
'grading': {'correctAnswers': {'answers': [{'value': '1115'}]}}, 'textQuestion': {}}}}]}
The official documentation has too few examples for me to understand how to apply it to my form.
update = {
"requests": [{
"updateItem": {
"item": {
"title": "Homework video",
"description": "Quizzes in Google Forms",
"videoItem": {
"video": {
"youtubeUri": "https://www.youtube.com/watch?v=Lt5HqPvM-eI"
}
}
},"location": {
"index": 0},
"updateMask": "description,youtubeUri"
}
}]
}
question_setting = service.forms().batchUpdate(
formId=form_id, body=update).execute()
From your following reply,
I want to update the youtubeUri item and use a new URL. How can I do this? i have two question use the video,how do i update the first question URL ?
I understood your question is as follows.
You want to update youtubeUri of 1st question in Google Forms using googleapis for python.
In this case, how about the following sample script?
Sample script:
service = # Please use your client
formId = "###" # Please set your Google Form ID.
after = "https://www.youtube.com/watch?v=###" # Please set YouTube URL you want to replace. In this sample, the existing URL is changed to this URL.
res = service.forms().get(formId=formId).execute()
itemIds = [[i, e["itemId"]] for i, e in enumerate(res.get("items")) if "videoItem" in e]
topItem = itemIds[0] # From your question, `youtubeUri` of the 1st question.
req = {
"requests": [
{
"updateItem": {
"item": {
"itemId": topItem[1],
"videoItem": {
"video": {
"youtubeUri": after,
}
},
},
"location": {"index": topItem[0]},
"updateMask": "videoItem.video.youtubeUri",
}
}
]
}
service.forms().batchUpdate(formId=formId, body=req).execute()
When this script is run, first, all items are retrieved. And, the item IDs including youtubeUri are retrieved. And, using the 1st item ID, the value of youtubeUri is changed to the value of after you set.
Note:
In this sample script, it supposes that you have already been able to get and out values to Google Form using Google Form API. Please be careful about this.
Reference:
Method: forms.batchUpdate

Parse JSON value into key-value attributes

I got the following output from my API:
{
'Type': 'Notification',
'MessageId': 'xxx',
'TopicArn': 'xxx',
'Subject': 'xxx',
'Message': 'EventType=Delete, FriendlyType=was deleted, '
'Timestamp=2021-11-08T15:30:45Z, UserId=1111, UserName=me#me.com, '
'IPAddr=(empty), AccountId=22222, AccountName=test-account, '
'ProjectId=test-project',
'Timestamp': '2021-11-08T15:30:46.214Z',
'SignatureVersion': '1'
}
Now I want to access the "Message" variable - once I am in, and get the following output (as already visible in the previous mentioned JSON):
EventType=Delete, FriendlyType=was deleted, Timestamp=2021-11-08T15:30:45Z, UserId=1111, UserName=me#me.com, IPAddr=(empty), AccountId=22222, AccountName=test-account, ProjectId=test-project
How can I now access the keys like EventType, FriendlyType, etc.? I assume that I have to convert this output at first to a valid JSON, but I am currently baffled.
In case that you are not able to receive the Message data as a JSON, a way to handle the situation is convert the message string into a dict <key>:<value>:
message_as_dict = dict(map(lambda var: var.strip().split("=") ,message.split(",")))
NOTICE the .strip() in order to remove the spaces on the beginning of the key.
That shoud create a dictionary with the following structure:
{'EventType': 'Delete', 'FriendlyType': 'was deleted', 'Timestamp': '2021-11-08T15:30:45Z', 'UserId': '1111', 'UserName': 'me#me.com', 'IPAddr': '(empty)', 'AccountId': '22222', 'AccountName': 'test-account', 'ProjectId': 'test-project'}
Then you can access to the values with, for example:
print(message_as_dict["UserName"])
> me#me.com
you can parse your string spliting and then use it to create a dict. Maybe it's not the best solution but it's a simple one.
response = {
'Type': 'Notification',
'MessageId': 'xxx',
'TopicArn': 'xxx',
'Subject': 'xxx',
'Message': 'EventType=Delete, FriendlyType=was deleted, Timestamp=2021-11-08T15:30:45Z, UserId=1111, UserName=me#me.com, IPAddr=(empty), AccountId=22222, AccountName=test-account, ProjectId=test-project',
'Timestamp': '2021-11-08T15:30:46.214Z',
'SignatureVersion': '1'
}
keyVals = [el.split('=') for el in response['Message'].split(', ')]
subdict = {}
for key,val in keyVals:
subdict[key] = val
As mentioned in one of the answer, you can parse your Message string, but I too feel it won't be the best solution. What I noticed is that your JSON is not in proper format. See below for proper JSON you should be getting from your API.
{
"Type": "Notification",
"MessageId": "xxx",
"TopicArn": "xxx",
"Subject": "xxx",
"Message": {
"EventType": "Delete",
"FriendlyType": "was deleted",
"Timestamp": "2021-11-08T15:30:45Z",
"UserId": "1111",
"UserName": "me#me.com",
"IPAddr": "(empty)",
"AccountId": "22222",
"AccountName": "test-account",
"ProjectId": "test-project"
},
"SignatureVersion": "1"
}
Once you are able to get this output, you may further access nested objects. For example, to access FriendlyType from Message, you can simply say, body.Message.FriendlyType. body here means your entire JSON object.
You could do it by splitting the 'Message' string up into (key, value) pairs and constructing a dictionary from them:
from pprint import pprint
output = {'Type': 'Notification',
'MessageId': 'xxx',
'TopicArn': 'xxx',
'Subject': 'xxx',
'Message': 'EventType=Delete, FriendlyType=was deleted, '
'Timestamp=2021-11-08T15:30:45Z, UserId=1111, UserName=me#me.com, '
'IPAddr=(empty), AccountId=22222, AccountName=test-account, '
'ProjectId=test-project',
'Timestamp': '2021-11-08T15:30:46.214Z',
'SignatureVersion': '1'}
msg_dict = dict(pair.split('=') for pair in output['Message'].split(', '))
pprint(msg_dict, sort_dicts=False)
Output:
{'EventType': 'Delete',
'FriendlyType': 'was deleted',
'Timestamp': '2021-11-08T15:30:45Z',
'UserId': '1111',
'UserName': 'me#me.com',
'IPAddr': '(empty)',
'AccountId': '22222',
'AccountName': 'test-account',
'ProjectId': 'test-project'}

How to subtract key out of Json api response and check if there are more keys, and if so put them in a list?

So I have a complex problem, I have a JSON API response with the key: 'key' in 'persons'
but in some cases there is more than 1 'key', I tried to make a for loop to go through the response but it will print it like 20 times. Also, I have no idea to put those 'keys' in a list or a place where I can access them.
to make it a bit easier i have the response that i get out of my .request
{'id': 'a2b1109e-e142-4559-984c-3f9997b1db6a', 'externalId': None, 'name': 'tyr', 'description': '', 'client': '', 'reference': '56345', 'isMonitoring': False, 'monitoringSince': None, 'hasRiskProfile': True, 'riskProfile': 5, 'monitorFrequency': 4, 'mainBindable': None, 'organizationId': '65647b97-5ada-4362-bb3f-cae016722be6', 'userId': 'dd3cc015-e5cf-4a03-9408-74b102900836', 'createDate': '2021-03-23T11:29:55.2027037Z', 'updateDate': '2021-03-23T11:29:55.2027039Z', 'lastMonitorDate': '2021-03-23T11:29:55.2027039Z', 'persons': [{'firstname': 'ya', 'surname': 'o', 'dateOfBirth': '', 'updatedWithIdinIdentificationRequestPerson': None, 'relatedList': None, 'updatedWithIdinIdentificationRequestPersonDate': None, 'history': [], 'fullname': 'ya o', 'externalId': None, 'key': '8b92c210-eee6-4ab2-a093-48e4428af7f8', 'searchResults': [], 'requests': [], 'createDate': '2021-03-23T11:29:57.3853552Z', 'updateDate': '2021-03-23T11:29:57.3853553Z', 'archivedDate': None, 'isArchived': False, 'hasPepSearchResults': False, 'notes': []}], 'businesses': [], 'monitorIds': [], 'addresses': [], 'notifcations': [], 'monitors': []}
the number of keys can be different each time, so I will need to make a check to see if the key that gets back is already existing if so then do nothing, if the key is not existing then save that key in a variable.
here is a example of a response when there are 2 keys"key",
{'id': '44b2203b-b2c8-41f0-8fde-b697ec02a8c8', 'externalId': None, 'name': 'tyr', 'description': '', 'client': '', 'reference': '56345', 'isMonitoring': False, 'monitoringSince': None, 'hasRiskProfile': True, 'riskProfile': 5, 'monitorFrequency': 4, 'mainBindable': None, 'organizationId': '65647b97-5ada-4362-bb3f-cae016722be6', 'userId': 'dd3cc015-e5cf-4a03-9408-74b102900836', 'createDate': '2021-03-23T20:58:53.0345703Z', 'updateDate': '2021-03-23T20:58:53.0345705Z', 'lastMonitorDate': '2021-03-23T20:58:53.0345706Z', 'persons': [{'firstname': 'marnox', 'surname': 'bolier', 'dateOfBirth': '', 'updatedWithIdinIdentificationRequestPerson': None, 'relatedList': None, 'updatedWithIdinIdentificationRequestPersonDate': None, 'history': [], 'fullname': 'marnox bolier', 'externalId': None, 'key': '68e4a9ad-2431-490f-a216-61a0cbd81c57', 'searchResults': [{'at': '2021-03-23T20:58:54.6796804Z', 'totalHits': 0, 'type': None, 'results': [{'paymentRequired': False, 'service': None, 'source': 'CIR', 'items': [], 'count': 0}, {'paymentRequired': False, 'service': 'VaV61', 'source': 'Entity', 'items': [], 'count': 0}], 'requestable': {'id': 'bf9dea30-2f4a-467a-a7b1-6765ceaee517', 'name': 'marnox bolier', 'createDate': '2021-03-23T20:58:55.5409494Z', 'updateDate': '2021-03-23T20:58:55.5409495Z', 'type': 'NotFoundPerson', 'sourceKey': 'A135D3C449EA15C66B6444611E2C97EC', 'picture': None, 'properties': {}, 'resultKey': None, 'data': None, 'archivedDate': None, 'isArchived': False}, 'cachedResult': False}], 'requests': [{'id': '57866866-85c4-43d8-8caa-b47a90b12be4', 'name': 'marnox bolier (TO UPDATE)', 'createDate': '2021-03-23T20:58:56.3090064Z', 'updateDate': '2021-03-23T20:58:56.3090064Z', 'type': 'NotFoundPerson', 'sourceKey': 'AB1AD3379D84D5D2404CF8326CDA054D', 'picture': None, 'properties': {}, 'resultKey': None, 'data': None, 'archivedDate': None, 'isArchived': False}], 'createDate': '2021-03-23T20:58:53.912784Z', 'updateDate': '2021-03-23T20:58:53.912784Z', 'archivedDate': None, 'isArchived': False, 'hasPepSearchResults': True, 'notes': []}, {'firstname': 'marnix', 'surname': 'bolier', 'dateOfBirth': '', 'updatedWithIdinIdentificationRequestPerson': None, 'relatedList': None, 'updatedWithIdinIdentificationRequestPersonDate': None, 'history': [], 'fullname': 'marnix bolier', 'externalId': None, 'key': 'c0475154-530e-4802-b215-1d26a2c7f208', 'searchResults': [], 'requests': [], 'createDate': '2021-03-23T20:58:56.9078002Z', 'updateDate': '2021-03-23T20:58:56.9078002Z', 'archivedDate': None, 'isArchived': False, 'hasPepSearchResults': False, 'notes': []}], 'businesses': [], 'monitorIds': [], 'addresses': [], 'notifcations': [], 'monitors': []}
update i solved my first problem getting more than 1 key with a for loop:
for persons in api_response['persons']:
print(persons['key'])
output:
0b8eb227-0105-40a3-bc8b-8e3ef345a3f3
d9b68e7a-ffdd-44ea-86a4-ea4c541146b4
how can I only save the last result so in this case
d9b68e7a-ffdd-44ea-86a4-ea4c541146b4
Assuming you are using requests to fetch the data from the api your response will simply have a json() function attached. Meaning you can do something like this:
import requests
response = requests.get("example.com/api/random/endpoint")
data = response.json()
The json function in turn does the equivalent of json.loads() with the content of the response. Assuming your API returns a JSON object this will be converted to a dictionary (in accordance with the json conversion table.
After that you can follow go2nirvana's answer and manipulate this dictionary as you would any dict. For example using data.pop("key") to remove the value at that key, iterate over the dictionary, or whatever else you can do with a dictionary.
Admittedly your question is a bit vague and I am not sure exactly what you want to do with the data you recieve, but this is how you get that data in a form that is easy to work with within python.

How to extract values from list and store it as dictionary(key-value pair)?

I need to extract 2 values from this list of dictionary and store it as a key-value pair.
Here I attached sample data..Where I need to extract "Name" and "Service" from this input and store it as a dictionary. Where "Name" is Key and corresponding "Service" is its value.
Input:
response = {
'Roles': [
{
'Path': '/',
'Name': 'Heera',
'Age': '25',
'Policy': 'Policy1',
'Start_Month': 'January',
'PolicyDocument':
{
'Date': '2012-10-17',
'Statement': [
{
'id': '',
'RoleStatus': 'New_Joinee',
'RoleType': {
'Service': 'Service1'
},
'Action': ''
}
]
},
'Duration': 3600
},
{
'Path': '/',
'Name': 'Prem',
'Age': '40',
'Policy': 'Policy2',
'Start_Month': 'April',
'PolicyDocument':
{
'Date': '2018-11-27',
'Statement': [
{
'id': '',
'RoleStatus': 'Senior',
'RoleType': {
'Service': ''
},
'Action': ''
}
]
},
'Duration': 2600
},
]
}
From this input, I need output as a dictionary type.
Output Format: { Name : Service }
Output:
{ "Heera":"Service1","Prem" : " "}
My try:
Role_name =[]
response = {#INPUT WHICH I SPECIFIED ABOVE#}
roles = response['Roles']
for role in roles:
Role_name.append(role['Name'])
print(Role_name)
I need to pair the name with its corresponding service. Any help would be really appreciable.
Thanks in advance.
You just have to write a long line which can reach till the key 'Service'.
And you a syntax error in line Start_Month': 'January') and 'Start_Month': 'April'). You can't have one unclosed brackets.
Fix it and run the following.
This is the code:
output_dict = {}
for r in response['Roles']:
output_dict[r["Name"]] = r['PolicyDocument']['Statement'][0]['RoleType']['Service']
print(output_dict)
Output:
{'Heera': 'Service1', 'Prem': ''}
You just have to do like this:
liste = []
for role in response['Roles']:
liste.append(
{
role['Name']:role['PolicyDocument']['Statement'][0]['RoleType']['Service'],
}
)
print(liste)
It seems your input data is structured kind of strange and I am not sure what the ) are doing next to the months since they make things invalid but here is a working script assuming you removed the parenthesis from your input.
response = {
'Roles': [
{
'Path': '/',
'Name': 'Heera',
'Age': '25',
'Policy': 'Policy1',
'Start_Month': 'January',
'PolicyDocument':
{
'Date': '2012-10-17',
'Statement': [
{
'id': '',
'RoleStatus': 'New_Joinee',
'RoleType': {
'Service': 'Service1'
},
'Action': ''
}
]
},
'Duration': 3600
},
{
'Path': '/',
'Name': 'Prem',
'Age': '40',
'Policy': 'Policy2',
'Start_Month': 'April',
'PolicyDocument':
{
'Date': '2018-11-27',
'Statement': [
{
'id': '',
'RoleStatus': 'Senior',
'RoleType': {
'Service': ''
},
'Action': ''
}
]
},
'Duration': 2600
},
]
}
output = {}
for i in response['Roles']:
output[i['Name']] = i['PolicyDocument']['Statement'][0]['RoleType']['Service']
print(output)
This should give you what you want in a variable called role_services:
role_services = {}
for role in response['Roles']:
for st in role['PolicyDocument']['Statement']:
role_services[role['Name']] = st['RoleType']['Service']
It will ensure you'll go through all of the statements within that data structure but be aware you'll overwrite key-value pairs as you traverse the response, if they exist in more than a single entry!
A reference on for loops which might be helpful, illustrates using if statements within them which can help you to extend this to check if items already exist!
Hope that helps

Not understanding why I'm getting a list index error

I'm writing some code to automate some of my b2b email scraping. I have a function, hunter.domain_search(url), that outputs a dictionary with lists as some keys like this
{
'domain': 'turbotitleloan.com',
'webmail': False,
'pattern': None,
'organization': None,
'emails': [
{
'value': 'support#turbotitleloan.com',
'type': 'generic',
'confidence': 6,
'sources': [
{
'domain': 'turbotitleloan.com',
'uri': 'http://turbotitleloan.com/car-title-loans/title-loan-faqs',
'extracted_on': '2016-06-10'
},
{
'domain': 'turbotitleloan.com',
'uri': 'http://turbotitleloan.com/contact',
'extracted_on': '2016-06-10'
},
{
'domain': 'turbotitleloan.com',
'uri': 'http://turbotitleloan.com/faq',
'extracted_on': '2015-01-30'
}
],
'first_name': None,
'last_name': None,
'position': None,
'linkedin': None,
'twitter': None,
'phone_number': None
},
{
'value': 'underwriting#turbotitleloan.com',
'type': 'generic',
'confidence': 5,
'sources': [
{
'domain': 'turbotitleloan.com',
'uri': 'http://turbotitleloan.com/faq',
'extracted_on': '2016-05-02'
},
{
'domain': 'turbotitleloan.com',
'uri': 'http://turbotitleloan.com/car-title-loans/what-to-expect',
'extracted_on': '2016-06-10'
},
{
'domain': 'turbotitleloan.com',
'uri': 'http://turbotitleloan.com/car-title-loans/title-loan-faqs',
'extracted_on': '2016-06-10'
}
],
'first_name': None,
'last_name': None,
'position': None,
'linkedin': None,
'twitter': None,
'phone_number': None
}
]
}
and I want my code to return the values paired with the key 'values', which would just be a series of email addresses. Urls is just a list of domain names. Here's where I think my issue is
for url in urls:
result=hunter.domain_search(url)
nResult=result['emails']
nResult[0]['value']
It outputs a single email address and then I get a list index out of range error. I'm not getting why I'm encountering this error. Each time it goes through the loop its working with a new list, and all of these lists should have a first element, which is where the dictionary I want to access is stored. So why is my loop working on the first list, and not on subsequent ones?
The index error is probably caused by your function returning a result with an empty emails list. Try this to skip entries without emails.
for url in urls:
result=hunter.domain_search(url)
nResult=result['emails']
if nResult:
print(nResult[0]['value'])
else:
print('no emails found in', url)

Categories