-2

I have a response object from a request in the form of:

url = 'http://localhost:8000/some-endpoint'
body = {
    'key': 'val'
}
response = requests.post(url, json=body)

And would like to access a key from the response in the form of:

[
  [
    "{\"somekey\": \"abcabcabc\", \"expires_in\": 86400}"
  ]
]

I have tried using various methods for accessing someKey but get errors

response.json()
# TypeError: unhashable type: 'dict'


json.dumps(response).json()
# TypeError: Object of type Response is not JSON serializable


response[0]['somekey']
# TypeError: 'Response' object is not subscriptable


response.get('somekey')
# AttributeError: 'Response' object has no attribute 'get'


response.text
["{\"access_token\": \"j9U9QHChSrEVitXeZSv400AQfq3imq\", \"expires_in\": 86400, \"token_type\": \"Bearer\", \"scope\": \"read write\"}"]

response.text.json()
# 'str' object has no attribute 'json'

How can I access the value of somekey?

Note: response object is being wrapped for debugging in Postman like:

return Response({
    res.json().get('access_token')
}, status=200)
Matthew
  • 1,461
  • 3
  • 23
  • 49
  • would you be able to show us the results of `response.text`? it's pretty strange that you're getting that specific type of TypeError for `response.json()` – David Culbreth Sep 08 '21 at 16:15
  • @jarmod it is nested, and when using the `json.loads` method you cite it returns `TypeError: 'Response' object is not subscriptable` – Matthew Sep 08 '21 at 16:16
  • I see the last entry you added, and I'd really like to actually see the format of the string response you're getting. I'm aware that `str` objects will not have a `json()` method on them. – David Culbreth Sep 08 '21 at 16:20
  • @DavidCulbreth I see... I updated the question to more accurately describe what I see for the initial Postman response. – Matthew Sep 08 '21 at 16:24
  • 1
    I'm confused about the literal content of the text... in the first example, you have 2 sets of array brackets around it, and in the response, there is only one. Additionally, it seems that your django service has string-escaped the JSON payload? Could you copy the literal string output into a separate code block, just so I'm clear on this? Like, no extra characters or anything. just, literally what comes off the terminal. or Postman. either one works – David Culbreth Sep 08 '21 at 16:35
  • @DavidCulbreth the first `[[ ]]` double nested response is what `response` returns. – Matthew Sep 08 '21 at 17:43
  • @DavidCulbreth it looks like a literal string nested inside two arrays. – Matthew Sep 08 '21 at 17:44
  • Do you have control over the app server that generates this response? Can you verify that it sends a valid JSON string in the body and application/json content type? Or do this via browser devtools network capture. – jarmod Sep 08 '21 at 18:01
  • @jarmod There's a string nested in two arrays. If the string is unescaped and the first and last double quote are removed, it's valid JSON. However, it will require a few steps to parse out. – Matthew Sep 08 '21 at 18:05
  • Index Array > Index Array > Unescape > Remove First And Last Quote > Interpret as JSON – Matthew Sep 08 '21 at 18:06
  • @jarmod and no control over the server. – Matthew Sep 08 '21 at 18:06

2 Answers2

0

try the following:

Ensure your response returns valid JSON by declaring a JSON_HEADERS constant and passing it as an key word argument:

JSON_HEADERS = {
    'Content-Type': "application/json",
    'Accept': "application/json"
}

And then properly serialize your body variable and print the key you need:

body = json.dumps({
  'key': 'val'
})
response = requests.post(url, headers=JSON_HEADERS, json=body)

Your endpoint returns a list with a string at the first index. Try this:

r = json.loads(response[0])
r['key']
<value of key>

You need to convert the string to a dict object before you can access the key value pairs as expected.

0

The response can be parsed with the following method:

response.json()['somekey']

or more commonly

response.json().get('somekey')

From @DavidCulbreth

Response({res.json()['somekey']}, status=200) is atempting to put the response into a set(), which is why it throws TypeError: unhashable type: 'dict'.

Matthew
  • 1,461
  • 3
  • 23
  • 49
  • 1
    In your post, you said that `response.json()` causes `TypeError: unhashable type: 'dict'`. – jarmod Sep 08 '21 at 18:24
  • Just double checked and indeed that is the response from that scenario. – Matthew Sep 08 '21 at 18:31
  • you must be using that value elsewhere, because if the actual `json()` call was throwing the error, then `response.json()['somekey']` would be throwing the same error. – David Culbreth Sep 08 '21 at 18:33
  • Also, this has nothing to do with Django. you are using the `requests` library. – David Culbreth Sep 08 '21 at 18:34
  • @Matthew That statement just adds to the confusion. What do you mean? It cannot be the case that `response.json()['somekey']` works but `response.json()` causes TypeError. – jarmod Sep 08 '21 at 18:34
  • @DavidCulbreth updated answer regarding Django vs. `requests` library. – Matthew Sep 08 '21 at 18:35
  • @jarmod I'm not sure what to tell you, those are the responses I get back from Postman. – Matthew Sep 08 '21 at 18:35
  • What does Postman have to do with this? Your Python client makes an HTTP request, gets a response, and tries to parse that response as JSON. – jarmod Sep 08 '21 at 18:36
  • Maybe because it's wrapped like this? `return Response({res.json()['somekey']}, status=200)` – Matthew Sep 08 '21 at 18:36
  • @jarmod was using Postman to make requests to the API. It's a passthrough API that calls another API. – Matthew Sep 08 '21 at 18:37
  • Your question is about a Python HTTP client using requests, not about Postman. – jarmod Sep 08 '21 at 18:38
  • My question was about parsing the response. Anyways... the above answer works. Sorry that you're offended by the solution. – Matthew Sep 08 '21 at 18:39
  • 1
    @Matthew, `return Response({res.json()['somekey']}, status=200)` is atempting to put your response into a `set()`, which is why it was throwing that `TypeError: unhashable type: 'dict'` error. get rid of those curly brackets and make your life easier. – David Culbreth Sep 08 '21 at 18:40
  • I'm not offended, but you've wasted a lot of peoples time. Please try to avoid that in future. – jarmod Sep 08 '21 at 18:40
  • Will do. Thank you both for your help. – Matthew Sep 08 '21 at 19:28