Überprüfen Sie, ob ein Schlüssel vorhanden ist, und iterieren Sie das JSON-Array mit Python

130

Ich habe eine Reihe von JSON-Daten aus Facebook-Posts wie den folgenden:

{"from": {"id": "8", "name": "Mary Pinter"}, "message": "How ARE you?", "comments": {"count": 0}, "updated_time": "2012-05-01", "created_time": "2012-05-01", "to": {"data": [{"id": "1543", "name": "Honey Pinter"}]}, "type": "status", "id": "id_7"}

Die JSON-Daten sind halbstrukturiert und nicht alle gleich. Unten ist mein Code:

import json 

str = '{"from": {"id": "8", "name": "Mary Pinter"}, "message": "How ARE you?", "comments": {"count": 0}, "updated_time": "2012-05-01", "created_time": "2012-05-01", "to": {"data": [{"id": "1543", "name": "Honey Pinter"}]}, "type": "status", "id": "id_7"}'
data = json.loads(str)

post_id = data['id']
post_type = data['type']
print(post_id)
print(post_type)

created_time = data['created_time']
updated_time = data['updated_time']
print(created_time)
print(updated_time)

if data.get('application'):
    app_id = data['application'].get('id', 0)
    print(app_id)
else:
    print('null')

#if data.get('to'):
#... This is the part I am not sure how to do
# Since it is in the form "to": {"data":[{"id":...}]}

Ich möchte, dass der Code die to_id als 1543 druckt, sonst 'null'

Ich bin mir nicht sicher, wie ich das machen soll.

pravi
quelle

Antworten:

162
import json

jsonData = """{"from": {"id": "8", "name": "Mary Pinter"}, "message": "How ARE you?", "comments": {"count": 0}, "updated_time": "2012-05-01", "created_time": "2012-05-01", "to": {"data": [{"id": "1543", "name": "Honey Pinter"}]}, "type": "status", "id": "id_7"}"""

def getTargetIds(jsonData):
    data = json.loads(jsonData)
    if 'to' not in data:
        raise ValueError("No target in given data")
    if 'data' not in data['to']:
        raise ValueError("No data for target")

    for dest in data['to']['data']:
        if 'id' not in dest:
            continue
        targetId = dest['id']
        print("to_id:", targetId)

Ausgabe:

In [9]: getTargetIds(s)
to_id: 1543
inspectorG4dget
quelle
6
Warum werden diese expliziten inÜberprüfungen durchgeführt und raiseob sie fehlen? Greifen Sie einfach ohne Überprüfung darauf zu, und Sie erhalten genau das gleiche Verhalten (außer mit a KeyErroranstelle von a ValueError).
Abarnert
98

Wenn Sie nur prüfen möchten, ob ein Schlüssel vorhanden ist oder nicht

h = {'a': 1}
'b' in h # returns False

Wenn Sie überprüfen möchten, ob ein Wert für den Schlüssel vorhanden ist

h.get('b') # returns None

Gibt einen Standardwert zurück, wenn der tatsächliche Wert fehlt

h.get('b', 'Default value')
athap
quelle
gibt 'null' und nicht 'Standardwert' zurück, wie für b erwartet, wenn {'a': 1, 'b': null}
MikeL
16

Es wird empfohlen, Hilfsprogrammmethoden für solche Dinge zu erstellen, damit sich die Logik der Attributvalidierung immer dann an einer Stelle befindet, wenn sie geändert werden muss, und der Code für die Follower besser lesbar ist.

Erstellen Sie beispielsweise eine Hilfsmethode (oder eine Klasse JsonUtilsmit statischen Methoden) in json_utils.py:

def get_attribute(data, attribute, default_value):
    return data.get(attribute) or default_value

und verwenden Sie es dann in Ihrem Projekt:

from json_utils import get_attribute

def my_cool_iteration_func(data):

    data_to = get_attribute(data, 'to', None)
    if not data_to:
        return

    data_to_data = get_attribute(data_to, 'data', [])
    for item in data_to_data:
        print('The id is: %s' % get_attribute(item, 'id', 'null'))

WICHTIGE NOTIZ:

Es gibt einen Grund, den ich data.get(attribute) or default_valueanstelle von einfach verwende data.get(attribute, default_value):

{'my_key': None}.get('my_key', 'nothing') # returns None
{'my_key': None}.get('my_key') or 'nothing' # returns 'nothing'

In meinen Anwendungen ist das Abrufen eines Attributs mit dem Wert 'null' dasselbe wie das Abrufen des Attributs überhaupt nicht. Wenn Ihre Verwendung anders ist, müssen Sie dies ändern.

MikeL
quelle
4
jsonData = """{"from": {"id": "8", "name": "Mary Pinter"}, "message": "How ARE you?", "comments": {"count": 0}, "updated_time": "2012-05-01", "created_time": "2012-05-01", "to": {"data": [{"id": "1543", "name": "Honey Pinter"}, {"name": "Joe Schmoe"}]}, "type": "status", "id": "id_7"}"""

def getTargetIds(jsonData):
    data = json.loads(jsonData)
    for dest in data['to']['data']:
        print("to_id:", dest.get('id', 'null'))

Versuch es:

>>> getTargetIds(jsonData)
to_id: 1543
to_id: null

Oder wenn Sie nur Werte überspringen möchten, bei denen IDs fehlen, anstatt zu drucken 'null':

def getTargetIds(jsonData):
    data = json.loads(jsonData)
    for dest in data['to']['data']:
        if 'id' in to_id:
            print("to_id:", dest['id'])

So:

>>> getTargetIds(jsonData)
to_id: 1543

Natürlich möchten Sie im wirklichen Leben wahrscheinlich nicht printjede ID, sondern sie speichern und etwas mit ihnen tun, aber das ist ein anderes Problem.

abarnert
quelle
4
if "my_data" in my_json_data:
         print json.dumps(my_json_data["my_data"])
Ajit Surendran
quelle
4

Zu diesem Zweck habe ich eine winzige Funktion geschrieben. Fühlen Sie sich frei, wiederzuverwenden,

def is_json_key_present(json, key):
    try:
        buf = json[key]
    except KeyError:
        return False

    return True
tabdiukov
quelle