0

I've got some data in a JSON file that I'm trying to manipulate. Having not done much with JSON before, I'm wondering if it's possible to select an object by one of its values rather than the index.

Here's my json file:

{"device":[
    {"id": 0, "name": "iPhone 6", "width": 750, "height": 1334},
    {"id": 1, "name": "iPhone 6 Plus", "width": 1242, "height": 2208},
    {"id": 2, "name": "Galaxy S6", "width": 1440, "height": 2560}
]}

I want to select object of id = 0 and print out the name value. I realise that the typical way to do this would be to select the object via its index value, which in this case matches up with the id value meaning I'd do something like:

print(json_obj['device'][0]['name'])

That would print the name but it relies on the index being equal to the id, which in an ideal world it would be. Perhaps a better way would be to just take the index as the id and remove that field altogether so there is no confusion? Seems like a duplicate index now that I think about it, though it exists so that I can store an ID in my database and edit the name independently in the JSON file yet have something concrete to denote the order (i.e. someone might add a device to the top of the file thus shifting the index of every other device - breaking the whole system). I get the feeling I'm barking up the wrong data structure and there's no way to do something along the lines of:

print(json_obj['device'][id = 0]['name']

Am I right?

Hexodus
  • 369
  • 6
  • 18
  • I think you need a filter-like function such as http://stackoverflow.com/questions/2844516/how-to-filter-a-dictionary-according-to-an-arbitrary-condition-function – Xiongbing Jin Apr 20 '16 at 17:42
  • You don't need to keep the data representation in the form the JSON had it after you parse the JSON. You can construct your own, more convenient data structures. – user2357112 Apr 20 '16 at 17:42

3 Answers3

3

Minor note: this really has nothing to do with JSON. Once you've parsed the data, it's no longer JSON, but it's regular data in memory (lists, strings, dictionaries, etc.)

An easy way to do this is with a loop:

for device in data['device']:
    if device['id'] == 5:
        print('Device:', device['name'])
        break
else:
    print('No such device')

You can also do this with comprehensions or other sophisticated (and terse) ways, but the above method is perhaps the more straightforward and simple.

There is also a system called JSONPath (with its Python module) which can let you express the queries in a more declarative and natural fashion.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
0

Nothing as efficient obviously but you can do a something like:

[x['name'] for x in json_obj['device'] if x['id'] == 0][0]

That builds a list of all elements with id == 0. It's harder to work with in the id not found case.

from a design point of view if you have control over the origination of the data, or you might want to process it, is something more like:

{'device': {
    0: {"id": 0, "name": "iPhone 6", "width": 750, "height": 1334},
    1: {"id": 1, "name": "iPhone 6 Plus", "width": 1242, "height": 2208},
    2: {"id": 2, "name": "Galaxy S6", "width": 1440, "height": 2560}
    }
}

If you don't have control you can get there by:

json_obj['device'] = dict(zip([x['id'] for x in json_obj['device']), json_obj['device'])
json_obj['device'][id]['name']

In practice you probably don't just want to overwrite the existing variables, but this way keeps everything else the same.

nephlm
  • 543
  • 3
  • 11
0

There are definitely many simple ways to do this.

data = {
    "device": [
        {"id": 0, "name": "iPhone 6", "width": 750, "height": 1334},
        {"id": 1, "name": "iPhone 6 Plus", "width": 1242, "height": 2208},
        {"id": 2, "name": "Galaxy S6", "width": 1440, "height": 2560}
    ]
}

items = data.get('device')
for item in items:
    if item.get('id') == 0:
        print(item.get('name'))
HEADLESS_0NE
  • 3,416
  • 4
  • 32
  • 51