Check value in dynamically changing nested JSON - python

I'm trying to get some JSONs using requests library. These JSONs always have status code 200 and normally look so:
{
"response":{
"count":2,
"items":[
{
"id":1,
"first_name":"Lorem",
"last_name":"Ipsum",
"is_closed":false,
"can_access_closed":true,
"track_code":"c8b0bA"
},
{
"id":2,
"first_name":"Lorem",
"last_name":"Ipsum",
"is_closed":false,
"can_access_closed":true,
"track_code":"0776a72"
}
]
}
}
But can be like:
{
"error":{
"error_code":6,
"error_msg":"Too many requests per second",
"request_params":[
{
"key":"count",
"value":"10"
},
{
"key":"",
"value":""
},
{
"key":"v",
"value":"5.103"
}
]
}
}
So I'm trying to request again JSONs that getting error. My current code:
for i in range(20):
while True:
r = requests.get('https://api.github.com/events') #example
json = r.json()
if 'error_code' in json['error']:
continue
break
And I'm getting KeyError: 'error'.
I also tried something like this:
for i in range(20):
while True:
r = requests.get('https://api.github.com/events') #example
json = r.json()
if 'error_code' in json.get('error'):
continue
break
But got TypeError: argument of type 'NoneType' is not iterable

Since json.get('error') can give you None in case error is not inside json, then it is understandable that you get this error. Why don't you do the following:
if 'error' in json:
# code
Also, you should not do while True requests in case of Too many requests. Sleep or at least do exponential backoff in between your requests.

Check if error exists in json and then check the value for error_code:
if json.get('error') and 'error_code' in json.get('error'):
Alternately,
error_code = json.get('error', {}).get{'error_code')
if error_code:
# take action

Try the following code:
import json #change over here
for i in range(20):
while True:
r = requests.get('https://api.github.com/events') #example
json = json.loads(r)
if 'error_code' in json['error']:
continue
break

Related

JSON key and value

I am trying to get the values from objects in the following JSON response:
[
{
"compositionId": "-Mkl92Mii2UF3xzi1q7L",
"compositionName": null,
"mainComposition": true,
"animation": {
"state": "Out1"
}
},
{
"compositionId": "bbbbbb",
"compositionName": null,
"mainComposition": true,
"animation": {
"state": "Out1"
}
}
]
What I would like to get in a loop is all the compositionIds but I don't get the correct output.
I can dump the complete JSON with the following code:
import requests
import json
url = 'http://192.168.1.33/data'
r = requests.get(url)
data = json.loads(r.content.decode())
json_str = json.dumps(data)
resp = json.loads(json_str)
print (resp)
You can simply use the requests module, in fact it does provide a builtin json decoder, that is the .json() function. Done that, you can simply iterate over your json objects with a simple for.
You could do something similar to this:
import requests
url = 'http://192.168.1.33/data'
r = requests.get(url)
my_json_file = r.json()
for json_object in my_json_file:
# Do something with json_object['compoitionId']
pass
Try something like this:
import requests
import json
url = 'http://192.168.1.33/data'
r = requests.get(url)
data = json.loads(r.content.decode())
print([d['compositionId'] for d in data])

how filter json python element

I have a json that I have via a python request, and I need to check if the "extension" key is equal to "txt", if so give a message.
from requests import get
import json
url = get('http://', auth = ('user', 'password'))
data_JSON = url.json()
for element in json['diffs']:
if element['extension'] == 'txt':
print ("have txt")
The json that returns from the request is this:
{
"fromHash":"***",
"toHash":"BG",
"contextLines":10,
"whitespace":"SHOW",
"diffs":[
{
"source":{
"components":[
"arquivo1.txt"
],
"parent":"",
"name":"arquivo1.txt",
"extension":"txt",
"toString":"arquivo1.txt"
},
....
I want to check the extension key if the value is txt, if yes return a message
Use element['source']['extension'] instead of element['extension'] since extension is a key within element['source'] not element directly.
from requests import get
import json
url = get('http://', auth = ('user', 'password'))
data_JSON = url.json()
for element in data_JSON['diffs']:
if element['source']['extension'] == 'txt':
print('have txt')
There is no need to use a for loop to iterate over "diffs".
Simply use an index such as 0.
Take a look at the following data which represents your JSON structure.
sample_json = {
"diffs":[
{
"source":{
"extension":"txt",
}
}
]
}
It appears, our first key is called diffs which has a list value.
We can easily access the diffs list by using sample_json["diffs"]; This returns a list.
So we index it -> sample_json["diffs"][0]
We get a dictionary (go to source) -> sample_json["diffs"][0]["source"]
Look for the extensions key -> sample_json["diffs"][0]["source"]["extensions"]
I've given you an explanation so that later on in the future you can follow a similar process.
code
sample_json = {
"diffs":[
{
"source":{
"extension":"txt",
}
}
]
}
extension = sample_json["diffs"][0]["source"]["extension"]
if extension == "txt":
print("true")

Python requests, how to send json request without " "

my code looks like
data = {
"undelete_user":'false'
}
data_json = json.dumps(data)
print(data_json)
Output is:
{"undelete_user": "false"}
i need output to be without "" so it can look like
{"undelete_user": false}
otherwise when i send request, i will get "failed to decode JSON" error
import json
data = {
"undelete_user": False
}
data_json = json.dumps(data)
print(data_json)
All you had to do was remove 'false' and put False, because you're considering your false as a string, and it should be a boolean.
I hope it helped!

default value for missing value for a key in json in http output

I have situation where i get http response with missing value for a key.
import requests
http = requests.get(url, verify=False, auth=HTTPBasicAuth(self.username, self.password),
timeout=self.timeout, headers=headers)
http.text gives output but http.json doesn't give any output.I understand that this issue is because of Invalid json format.
'{"PLMNID":[
{
"mNc":,
"id":3,
"mcc":
},
{
"mNc":,
"id":4,
"mcc":
},
{
"mNc":,
"id":5,
"mcc":
},
{
"mNc":,
"id":6,
"mcc":
}}'
Currently I retrun http.json.I see no response and also no error.
Now i planning to return http.text output and some how add default value (may be '' or null)for missing key and proceed.
Do we have any python json api which will add default value for missing value for a key.
import json
text = '{"sa": 1, "df":[{"vc":1,"mn":2},{"vc":1,"mn":}]}'
len_text = len(text)
j = 0
js = None
while j <= len_text:
try:
js = json.loads(text)
except json.JSONDecodeError as mn :
if mn.msg == "Expecting value":
text1 = list(text)
text1.insert(mn.pos, 'null')
text = "".join(text1)
else:
print("Got other error than Expecting value at pos:{0} with error:{1}".format(mn.pos, mn.msg))
break
j += 1
print(js)
This code is checking for JSON decode error and when "Expecting value" msg appears it fills with "null" value at the index of JSON text. This repeated until it fills the "null" value or breaks if some other error msg appears.

Getting a specific value of JSON data

I'm getting a JSON data from RESTCONF HTTPS request, using the following code
https_request = 'https://' + host + '/restconf/data/' + operation
headers = {'Content-type': 'application/yang-data+json', 'Accept': 'application/yang-data+json'}
r = requests.get(https_request, auth=(user, password), headers=headers, verify=False)
print r.json()
The data I got is the following:
{
"Cisco-IOS-XE-segment-routing:ipv4": {
"prefixes": [
{
"ipprefix": "1.1.1.1/32",
"index": {
"range-start": 333,
"range": 1
}
}
]
}
}
Basically, I want to return the field's "range-start" value which is 333. I tried the following but it did not work.
for element in r:
id = element['range-start']
print(id)
Is there anyway to get that value?
From Python Console:
>>> import json
... data = json.loads('{"Cisco-IOS-XE-segment-routing:ipv4": {"prefixes": [{"ipprefix": "1.1.1.1/32", "index": {"range-start": 333, "range": 1}}]}}')
... print(data['Cisco-IOS-XE-segment-routing:ipv4']['prefixes'][0]['index']['range-start'])
333
>>>
You need to start at the beginning of the JSON and work your way to the key you want. To do this you need to start at Cisco-IOS-XE-segment-routing:ipv4.
prefixes = r.json()["Cisco-IOS-XE-segment-routing:ipv4"]["prefixes"]
id = prefixes[0]["index"]["range-start"]
If there are multiple prefixes you can loop over them and access each range-start.
Since you are looping over elements, I would suggest this approach using a helper function:
def get_id(element):
prefixes = r.json()["Cisco-IOS-XE-segment-routing:ipv4"]["prefixes"]
id = prefixes[0]["index"]["range-start"]
return id
Then you can do, as in your question:
for element in r:
id = get_id(element)
print(id)

Categories

Resources