Hoe JSON correct te analyseren met simplejson?

Ik kan de volgende JSON-reeks hebben:

{ "response" : [ [ { "name" : "LA_",
          "uid" : 123456
        } ],
      [ { "cid" : "1",
          "name" : "Something"
        } ],
      [ { "cid" : 1,
          "name" : "Something-else"
        } ]
    ] }

of een van de volgende:

{"error":"some-error"}

{ "response" : [ [ { "name" : "LA_",
          "uid" : 123456
        } ],
      [ { "cid" : "1",
          "name" : ""
        } ],
      [ { "cid" : 1,
          "name" : "Something-else"
        } ]
    ] }

{ "response" : [ [ { "name" : "LA_",
          "uid" : 123456
        } ] ] }

Dus ik weet niet zeker of alle kinderen en elementen er zijn. Is het genoeg om de volgende verificaties uit te voeren om de waarde Something te krijgen:

if jsonstr.get('response'):
    jsonstr = jsonstr.get('response')[1][0]
    if jsonstr:
        name = jsonstr.get('name')
        if jsonstr: # I don't need empty value
            # save in the database

Kan hetzelfde worden vereenvoudigd?

1

1 antwoord

Je bent niet zeker dat de volgorde van je innerlijke objecten hetzelfde zal zijn elke keer dat je het parseert, dus indexeren is geen veilige gok om te verwijzen naar de index van het object met het attribuut name ingesteld op < code> iets .

In plaats van alle if -instructies te nesten, kunt u wegkomen met het gebruik van een lijstbegrip . Merk op dat als u de code reactie doorloopt, u ​​een lijst met lijsten krijgt, elk met een woordenboek erin:

>>> data = {"response":[[{"uid":123456,"name":"LA_"}],[{"cid":"1","name":"Something"}],[{"cid":1,"name":"Something-else"}]]}
>>> [lst for lst in data.get('response')]
[[{'name': 'LA_', 'uid': 123456}], [{'name': 'Something', 'cid': '1'}], [{'name': 'Something-else', 'cid': 1}]]

Als u het eerste item in elke lijst indexeert ( lst [0] ), krijgt u een lijst met objecten:

>>> [lst[0] for lst in data.get('response')]
[{'name': 'LA_', 'uid': 123456}, {'name': 'Something', 'cid': '1'}, {'name': 'Something-else', 'cid': 1}]

Als u vervolgens een voorwaarde if aan uw lijstbegrip toevoegt om het kenmerk naam van de objecten te laten overeenkomen, krijgt u een lijst met een enkel item met het gewenste object:

>>> [lst[0] for lst in data.get('response') if lst[0].get('name') == 'Something']
[{'name': 'Something', 'cid': '1'}]

En door het eerste item in die definitieve lijst te indexeren, krijgt u het gewenste object:

>>> [lst[0] for lst in data.get('response') if lst[0].get('name') == 'Something'][0]
{'name': 'Something', 'cid': '1'}

Dus dan kun je dat gewoon veranderen in een functie en verder gaan met je leven:

def get_obj_by_name(data, name):
    objects = [lst[0] for lst in data.get('response', []) if lst[0].get('name') == name]
    if objects:
        return objects[0]

    return None

print get_obj_by_name(data, 'Something')
# => {'name': 'Something', 'cid': '1'}

print get_obj_by_name(data, 'Something')['name']
# => 'Something'

En het moet veerkrachtig zijn en Geen retourneren als de sleutel reactie niet wordt gevonden:

print get_obj_by_name({"error":"some-error"}, 'Something')
# => None
2
toegevoegd
Bedankt, @jathanism, voor een zo gedetailleerd antwoord. Eigenlijk is 'Iets' de waarde waar ik naar op zoek ben - het kan elke andere waarde zijn. Een derde partij geeft mij geen enkele identifier van dit element, dus ik moet op hun volgorde vertrouwen.
toegevoegd de auteur LA_, de bron
Graag gedaan. :)
toegevoegd de auteur jathanism, de bron