How would I prevent KeyError when grabbing a value from an API query JSON?
Explanation: I am calling an API for a user one at a time. Each user returns a JSON with a set of information. I am creating a dictionary from a few specific pieces of information in that JSON. However, sometimes users don't have a specific value (such as Role or Username). How can I write my program so it doesn't throw an exception and end the program when it can't find this value? And instead of throwing an exception it just enters a blank for that specific dictionary value? I have looked into .get but I cannot seem to get it to work with my specific use case.
Code:
APResponse = requests.request('POST', APurl, headers=headers, json={'offset': str(AssetPandaCurrentUser), 'limit': '1'})
APResponseJSON = APResponse.json()
AssetPandaUserDict = {
"Username": [APResponseJSON['objects'][0]['data']['field_52']],
"Role": [APResponseJSON['objects'][0]['data']['field_49']['value']],
"User Status": [APResponseJSON['objects'][0]['data']['field_6']['value']],
"Laptop Status": [],
"Laptop Serial": []
}
So if "Role" is blank or missing in the JSON, it will just set "Role" to a blank instead of throwing a KeyError exception.
I have tried this:
"Username": [APResponseJSON.get(['objects'][0]['data']['field_52'])]
But I get an error
TypeError: string indices must be integers
Any ideas?
You can use get() method.
For example:
"Role": [APResponseJSON.get(['objects'][0].get("data", {}).get("field_49"{}).get("value")]
of course if you are sure that APResponseJSON.get(['objects'][0] exists.
You can also prepare pydantic model to easily parse your response.
Related
I am trying to set a property tag according to Graph API documents as stated here: https://learn.microsoft.com/en-us/graph/api/resources/extended-properties-overview?view=graph-rest-1.0
I am trying to set a extended property on a MailFolder using the patch endpoint as listed here: https://learn.microsoft.com/en-us/graph/api/mailfolder-update?view=graph-rest-1.0&tabs=http
The content of the message is:
{'singleValueExtendedProperties': [{'id': 'String 0x10F4000B', 'value': 'true'}]}
However, i always get the result that indicates it fails due to a property value error:
{"error": {"code": "ErrorFolderSavePropertyError", "message": "The folder save operation failed due to invalid property values.", "innerError": { "request-id": "GUID", "date": "2019-11-12T19:44:02"}}}
Looking at the rules around MAPI and setting its values, it is trying to set the tag 0x10F4 using type 0x000B which is boolean. However, the extended properties only excepts strings. I am not sure how to set a boolean value into the value field.
the second half for the type goes where the string value is. So to post this, it will become
`{'singleValueExtendedProperties': [{'id': 'boolean 0x10F4', 'value': '**true**'}]}1
I am trying to get a key code from a json output.
But i cannot seem to get it, I get errors left and right.
Here is my code.
import requests
import time
import threading
import json
def ThreadRequest():
scrape_url = "https://pastebin.com/api_scraping.php?limit=1"
json_data = requests.get(scrape_url)
python_obj = json.loads(json_data.text)
print python_obj["key"]
ThreadRequest()
I either get
TypeError: list indices must be integers, not str
ValueError: No JSON object could be decoded
TypeError: expected string or buffer
I have tried many ways, different ways, even parsing by using .split() function.
I cannot seem to get the understanding of how to parse in json.
Here is the API output
[
{
"scrape_url": "https://pastebin.com/api_scrape_item.php?i=rkFbtGSj",
"full_url": "https://pastebin.com/rkFbtGSj",
"date": "1516914453",
"key": "rkFbtGSj",
"size": "3031",
"expire": "0",
"title": "",
"syntax": "text",
"user": ""
}
]
The first thing is that the requests module has a built-in JSON parsing method so just use that rather than trying to use the raw text response. Change:
python_obj = json.loads(json_data.text)
To:
python_obj = json_data.json()
Second, the data that you're interested in is in a dictionary. However, that dictionary is contained within a list. Take the 0th index of that list to get access to the dictionary, then access that by key (in this case, also called "key").
my_value = python_obj[0]['key']
I have a service that will respond to a request with a json blob, such as this:
{
"field1": 1,
"field2": "2",
"array": [1,2,3]
}
I know that I can test array by using EachLike, like this:
expected = {
"field1": Like(1),
"field2": Like("2"),
"array": EachLike(1)
}
The issue is that "array" is an optional field in the response. It may not exist at all, and if it doesn't, I still need the contract to validate. How do I define that a field in the response body must match a type if it exists, but that it may not exist at all?
From https://github.com/pact-foundation/pact-ruby/wiki/FAQ#why-is-there-no-support-for-specifying-optional-attributes
Why is there no support for specifying optional attributes?
Firstly, it is assumed that you have control over the provider's data (and consumer's data) when doing the verification tests. If you don't, then maybe Pact is not the best tool for your situation.
Secondly, if you think about it, if Pact supports making an assertion that element $.body.name may be present in a response, then you write consumer code that can handle an optional $.body.name, but in fact, the provider gives $.body.firstname, no test will ever fail to tell you that you've made an incorrect assumption. Remember that a provider may return extra data without failing the contract, but it must provide at minimum the data you expect.
I would recommend that you write one interaction where you require that the array is populated, so that you know how to deal with a populated array. Then leave it out of the other interactions altogether, and then it won't matter whether it's populated or not.
I am trying to loop around a json data sent by my android client. I used the code below but its not working for me. Any possible error that I am doing...????
def api_json(request):
try:
x101=json.loads(request.body)
print x101
for data in x101:
print data+"xp"
asset_code=data['asset_code']
credential=data['credential']
d1=data['d1']
d2=data['d2']
d3=data['d3']
angle=data['angle']
status=data['status']
operator=data['operator']
location=data['location']
print asset_code,credential,d1,d2,d3,angle,status,operator,location
v=Verification(asset_code=asset_code,
scan_time=datetime.datetime.now(),
credential=credential,
d1=d1,
d2=d2,
d3=d3,
angle=angle,
status=status,
operator=operator,
location=location,
image='')
v.save()
except:
print 'nope'
return HttpResponse('success')
error trace:
TypeError: string indices must be integers
Assuming your JSON decodes to a dictionary, for data in x101 iterates through the keys of that dictionary. So data['d1'] will give the TypeError that you see, "string indices must be integers".
Since you have given absolutely no details about what the data structure actually looks like, we can only guess, but you perhaps want to iterate through the dict's values with for data in x101.values().
In any case, you should definitely remove that try/except that does nothing except print "nope". Errors are there for a reason, and silencing them will only prevent you from debugging properly, as we see here.
Edit
x101 is just a single dict. You say that there will frequently be more than one dict, but it can't possibly work like that: the only way to have multiple dicts is to have them inside a list (ie a JSON array). And if so, they would have to always be in a list, even when there is just one. So your structure should be:
[
{
"angle": "10",
"asset_code": "XPS1020",
"credential": "wqw2323ds2",
"d1": "1",
"d2": "2",
"d3": "3",
"location": "Bangalore",
"operator": "pradeep",
"status": "1"
}
]
and then your code will work as is, whether there is a single dict or many.
I am currently trying to create a dictionary from a json formatted server response:
{"id": null,{"version": "1.1","result": "9QtirjtH9b","error": null}}
Therefore I am using json.loads(). But I always get the following error:
ValueError: Expecting property name: line 1 column 12 (char 12)
I know that this means that there is an error in the json syntax and I found some threads (like this one) here at stackoverflow, but they did not include an answer that solved my problem.
However, I was not sure if the null value within the json response causes the error, so I had a closer look at the json.org Reference Manual and it seems to be a valid syntax. Any ideas?
It's not valid. The outer object needs a property name for the second element; raw values are not valid in an object.
{"id": null, "somename":{"version": "1.1","result": "9QtirjtH9b","error": null}}
The problem here is the lack of a key for the nested object, not the null. You'd need to find a way to fix that syntax or parse it yourself.
If we make a few assumptions about the syntax, you should be able to use a regular expression to fix the JSON data before decoding:
import re
from itertools import count
def _gen_id(match, count=count()):
return '{1}"generated_id_{0}":{2}'.format(next(count), *match.groups())
_no_key = re.compile(r'(,)({)')
def fix_json(json_data):
return _no_key.sub(_gen_id, json_data)
This assumes that any ,{ combo indicates the location of a missing key, and generates one to insert there. That is a reasonable assumption to make, but may break things if you have string data with exactly that sequence.
Demo:
>>> json_data = '{"id": null,{"version": "1.1","result": "9QtirjtH9b","error": null}}'
>>> fix_json(json_data)
'{"id": null,"generated_id_0":{"version": "1.1","result": "9QtirjtH9b","error": null}}'
>>> json.loads(fix_json(json_data))
{u'id': None, u'generated_id_1': {u'version': u'1.1', u'result': u'9QtirjtH9b', u'error': None}}