Access JSON data in Python - python

header = {'Content-type': 'application/json','Authorization': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' }
url = 'https://sandbox-authservice.priaid.ch/login'
response = requests.post(url, headers = header, verify=False).json()
token = json.dumps(response)
print token['ValidThrough']
I want to print the ValidThrough Attribute in my webhook, which is received as JSON data via a POST call. I know this has been asked a number of times here, but print token['ValidThrough']isnt working for me.I receive the error "TypeError: string indices must be integers, not str"

Since the response already seems to be in json, there is no need to use json.dumps.
json.dumps on a dictionary will return a string which cannot be indexed obviously and hence that error.

a requests response .json() method already loads the content of the string to json.
You should use that, but your code later serializes it back to a string, and hence the error (token is a string representation of the dict you are expecting, not the dict). You should just omit the json.dumps(response) line, and use response['ValidThrough']
There's another error here, even if you assume that the .json() returns a string that should be unserialized again you should've used json.loads(response) in order to load it into a dict (not dumps to serialize it again)

Related

TypeError: string indices must be integers when using string split to pass paramerters to a json api

This the main drive Im using to call the call the functions from the mentioned call.
from primeReportController import PrimeReportController
input_str = input()
a = input_str.split(",",1)
report_date,report_name = a[0],a[1]
prime = PrimeReportController()
prime.generatePrimeReport(report_date,report_name)
This is the call function definition writhing the class
Also please note the function adds the json data to a sql database. The data is already formatted to fit the table schema.
Since the output of response.json() is {'message': 'The request is invalid.'}, it tells you that your request is invalid to the server, and that the returning value would not have the data structure you expected. So when you iterate over the response dict with:
for x in server_response:
What it really does is to iterate over the keys of the dict {'message': 'The request is invalid.'}, x becomes 'message' in the first iteration, so when you try to get the value of x['cell'], it consequently complains about your trying to access a string with a non-integer index.
You simply have to fix the request you send to the server first.

Get JSON response in Python, but in original JavaScript format

I am putting a JSON response into a variable via requests.json() like this:
response = requests.get(some_url, params=some_params).json()
This however converts JSON's original " to Python's ', true to True, null to None.
This poses a problem when trying to save the response as text and the convert it back to JSON - sure, I can use .replace() for all conversions mentioned above, but even once I do that, I get other funny json decoder errors.
Is there any way in Python to get JSON response and keep original JavaScript format?
json() is the JSON decoder method. You are looking at a Python object, that is why it looks like Python.
Other formats are listed on the same page, starting from Response Content
.text: text - it has no separate link/paragraph, it is right under "Response Content"
.content: binary, as bytes
.json(): decoded JSON, as Python object
.raw: streamed bytes (so you can get parts of content as it comes)
You need .text for getting text, including JSON data.
You can get the raw text of your response with requests.get(some_url, params=some_params).text
It is the json method which converts to a Python friendly format.

Python3 strange error with json.loads [duplicate]

This question already has answers here:
Let JSON object accept bytes or let urlopen output strings
(12 answers)
Closed 6 years ago.
I'm using flask in a web application that uses service api generates JSON response. The following part of the function works fine and returns JSON text output:
def get_weather(query = 'london'):
api_url = "http://api.openweathermap.org/data/2.5/weather?q={}&units=metric&appid=XXXXX****2a6eaf86760c"
query = urllib.request.quote(query)
url = api_url.format(query)
response = urllib.request.urlopen(url)
data = response.read()
return data
The output returned is:
{"coord":{"lon":-0.13,"lat":51.51},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"base":"cmc stations","main":{"temp":12.95,"pressure":1030,"humidity":68,"temp_min":12.95,"temp_max":12.95,"sea_level":1039.93,"grnd_level":1030},"wind":{"speed":5.11,"deg":279.006},"clouds":{"all":76},"dt":1462290955,"sys":{"message":0.0048,"country":"GB","sunrise":1462249610,"sunset":1462303729},"id":2643743,"name":"London","cod":200}
This mean that data is a string, does not it?
However, commenting the return data and then adding the following two lines:
jsonData = json.loads(data)
return jsonData
generates the following error:
TypeError: the JSON object must be str, not 'bytes'
What's wrong? data, the JSON object, previously returned as a string! I need to know where is the mistake?
The data returned by request library is a binary string while json.loads accepts strings so you need to convert the data (decode) to a string using the encoding that your request returns (which is usually ok to assume that it is UTF-8).
You should be able to just change your code to this:
return json.loads(data.decode("utf-8"))
PS: Storing the variable right before returning it is redundant so I simplified things

TypeError: list indices must be integers or slices, not str while parsing JSON

I am trying to print out at least one key value from the returned Json, as following this basic tutorial
response=None
booking_source = 'sourceBusinessName'
api_request ='http://api.com'
r = requests.get(api_request)
while response is None:
response = r.content.decode('utf-8')
data = json.loads(response)
print (data[booking_source])
return HttpResponse(data[booking_source])
But it returns TypeError: list indices must be integers or slices, not str
probably because I am giving an string instead of an integer to data when printing, but then what I am doing wrong here ?
With requests you can skip the decoding of the response and parsing it as JSON by using the response's json method:
r = requests.get(api_request)
data = r.json()
print data # so you can see what you're dealing with
At this point I suggest dumping out the value of data so that you can see the structure of the JSON data. Probably it is a JSON array (converted to a Python list) and you simply need to take the first element of that array before accessing the dictionary, but it's difficult to tell without seeing the actual data. You might like to add a sample of the data to your question.
Your JSON is an array at the top level, but you're trying to address it as if it were:
{
"sourceBusinessName": {
...
},
...
}

python requests json returns single quote

i'm playing a little with google places api and requests
I got :
r = requests.get(self.url, params={'key': KEY, 'location': self.location, 'radius': self.radius, 'types': "airport"}, proxies=proxies)
r returns a 200 code, fine, but I'm confused by what r.json() returns compared to r.content
extract of r.json() :
{u'html_attributions': [],
u'next_page_token': u'CoQC-QAAABT4REkkX9NCxPWp0JcGK70kT4C-zM70b11btItnXiKLJKpr7l2GeiZeyL5y6NTDQA6ASDonIe5OcCrCsUXbK6W0Y09FqhP57ihFdQ7Bw1pGocLs_nAJodaS4U7goekbnKDlV3TaL8JMr4XpQBvlMN2dPvhFayU6RcF5kwvIm1YtucNOAUk-o4kOOziaJfeLqr3bk_Bq6DoCBwRmSEdZj34RmStdrX5RAirQiB2q_fHd6HPuHQzZ8EfdggqRLxpkFM1iRSnfls9WlgEJDxGB91ILpBsQE3oRFUoGoCfpYA-iW7E3uUD_ufby-JRqxgjD2isEIn8tntmFDjzQmjOraFQSEC6RFpAztLuk7l2ayfXsvw4aFO9gIhcXtG0LPucJkEa2nj3PxUDl',
u'results': [{u'geometry': {u'location': {u'lat': -33.939923,
u'lng': 151.175276}},
while extract of r.content :
'{\n "html_attributions" : [],\n "next_page_token" : "CoQC-QAAABT4REkkX9NCxPWp0JcGK70kT4C-zM70b11btItnXiKLJKpr7l2GeiZeyL5y6NTDQA6ASDonIe5OcCrCsUXbK6W0Y09FqhP57ihFdQ7Bw1pGocLs_nAJodaS4U7goekbnKDlV3TaL8JMr4Xp
so r.content has the double quotes like a "correct" json object while r.json() seems to have changed all double-quotes in single-quotes.
Should I care about it or not ? I can still access r.json() contents fine, just wondered if this was normal for requests to return an object with single quotes.
The json() method doesn't actually return JSON. It returns a python object (read: dictionary) that contains the same information as the json data. When you print it out, the quotes are added for the sake of readability, they are not actually in your data.
Should I care about it or not?
Not.
What you can however is to add
jsonresponse=json.dump(requests.get(xxx).json())
in order to get valid json in jsonresponse.
Python uses single or double quotes for strings. By default, it'll display single quote for strings.
However, JSON specification only consider double quotes to mark strings.
Note that requests' response.json() will return native Python types which are slightly different from their JSON representation you can see with response.content.
You are seeing the single quotes because you are looking at Python, not JSON.
Calling Response.json attempts to parse the content of the Response as JSON. If it is successful, it will return a combination of dicts, lists and native Python types as #Two-Bit Alchemist alluded to in his comment.
Behind the scenes, The json method is just calling complexjson.loads on the response text (see here). If you dig further to look at the requests.compat module to figure out what complexjson is, it is the simplejson package if it is importable on the system (i.e. installed) and the standard library json package otherwise (see here). So, modulo considerations about the encoding, you can read a call to Response.json as equivalent to:
import requests
import json
response = requests.get(...)
json.loads(response.text)
TL;DR: nothing exciting is happening and no, what is returned from Response.json is not intended to be valid JSON but rather valid JSON transformed into Python data structures and types.

Categories

Resources