sejego
sejego

Reputation: 93

Comparing value in a JSON using Python

I receive a fairly uncomfortable JSON to work with, which looks as follows:

[
{
    "attributes": [
        {
            "type": "COMMAND",
            "name": "COMMAND",
            "value": [
                "buttonState"
            ]
        },
        {
            "type": "std_msgs.msg.Bool",
            "name": "buttonState",
            "value": {
                "data": false
            }
        }
    ],
    "type": "sensor",
    "id": "s_2"
}]

And I would like to compare a piece of data (more precisely - value of Button state) but I seem to fail. Tried following:

import requests
import json
yo = 1
switchPost = "http://192.168.0.104:7896/iot/d?k=123456789&i=san_1_switch&d=sw|{}"
robGet = "http://192.168.0.109:10100/robot/sen_2"

r = requests.get(robGet, headers={"content-type":"application/json"})
resp = json.loads(r.text)

for attrs in (resp['attributes']['value']):
    if attrs['data'] == false:
        yo = 100
        break
    
g = requests.post(switchPost.format(yo), headers={"content-type":"text/plain"})
print(r.text)

Unfortunately, the error I receive is the following:

for attrs in (resp['attributes']['value']):

TypeError: list indices must be integers, not str

Upvotes: 1

Views: 2065

Answers (3)

Sunitha
Sunitha

Reputation: 12025

resp is a list so, to get first element, access it as resp[0]. Same with resp[0]['attributes']

So you can access it as follows

resp[0]['attributes'][0]['value']

You can restructure your for loop as follows

for d in resp[0]['attributes']:
    if isinstance(d['value'], dict) and d['value'].get('data') == false:
        yo = 100
        break

Upvotes: 2

JMAA
JMAA

Reputation: 2067

In your JSON, the fact that it is wrapped in [ then ] means it is a JSON array, but with just one element.

So, as your error message suggests, resp needs an integer as its index, for which element of the array you want. resp[0] then refers to

{
    "attributes": [
        {
            "type": "COMMAND",
            "name": "COMMAND",
            "value": [
                "buttonState"
            ]
        },
        {
            "type": "std_msgs.msg.Bool",
            "name": "buttonState",
            "value": {
                "data": false
            }
        }
    ],
    "type": "sensor",
    "id": "s_2"
}

(notice no [] now, so it's a JSON object)

Then you want resp[0]['attributes'] to refer to the single part of this object, 'attributes' which again refers to an array.

Therefore for attribute in resp[0]['attributes'] will allow you to loop through this array.

To get the boolean value you want, you'll then want to find which element of that array has 'name' of 'buttonState' and check the corresponding 'value'.

In all, you're probably looking for something like:

for attribute in resp[0]['attributes']:
    if attribute['name'] == 'buttonState' and attribute['value']['data'] is False:
        # Do your thing here

Upvotes: 3

Mattias Nilsson
Mattias Nilsson

Reputation: 3767

The answer is in the error message I think:

TypeError: list indices must be integers, not str

The first entry in attributes has a value that is a list, so you can't get 'data' from that. Since you have a mix of types, you might need to check if 'value' is a list or a dict.

Edit: Jumped the gun here I think. @dennlinger gives an explanation to your error message. But you'll get it again once you're past that...

Upvotes: 1

Related Questions