Vérifiez si la clé existe et itérez le tableau JSON en utilisant Python

130

J'ai un tas de données JSON provenant de publications Facebook comme celle ci-dessous:

{"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"}

Les données JSON sont semi-structurées et tout n'est pas pareil. Voici mon 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":...}]}

Je veux que le code imprime le to_id en tant que 1543 sinon print 'null'

Je ne sais pas comment faire cela.

pravi
la source

Réponses:

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)

Production:

In [9]: getTargetIds(s)
to_id: 1543
inspecteurG4dget
la source
6
Pourquoi ces invérifications explicites et raisesi elles sont manquantes? Accédez-y simplement sans vérifier, et vous obtiendrez exactement le même comportement (sauf avec a KeyErrorau lieu de a ValueError).
abarnert le
101

Si tout ce que vous voulez, c'est vérifier si la clé existe ou non

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

Si vous souhaitez vérifier s'il existe une valeur pour la clé

h.get('b') # returns None

Renvoie une valeur par défaut si la valeur réelle est manquante

h.get('b', 'Default value')
athap
la source
renverra 'null' et non 'Default value' comme prévu pour b dans le cas de {'a': 1, 'b': null}
MikeL
16

C'est une bonne pratique de créer des méthodes utilitaires d'aide pour des choses comme ça afin que chaque fois que vous avez besoin de changer la logique de validation d'attribut, elle se trouve au même endroit et le code sera plus lisible pour les abonnés.

Par exemple, créez une méthode d'assistance (ou une classe JsonUtilsavec des méthodes statiques) dans json_utils.py:

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

puis utilisez-le dans votre projet:

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'))

NOTE IMPORTANTE:

Il y a une raison pour laquelle j'utilise data.get(attribute) or default_valueau lieu de simplement data.get(attribute, default_value):

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

Dans mes applications, obtenir un attribut avec la valeur «null» équivaut à ne pas obtenir l'attribut du tout. Si votre utilisation est différente, vous devez changer cela.

MikeL
la source
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'))

Essayez-le:

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

Ou, si vous souhaitez simplement ignorer les valeurs manquantes d'ID au lieu d'imprimer 'null':

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

Alors:

>>> getTargetIds(jsonData)
to_id: 1543

Bien sûr, dans la vraie vie, vous ne voulez probablement pas printchaque identifiant, mais les stocker et faire quelque chose avec eux, mais c'est un autre problème.

Abarnert
la source
4
if "my_data" in my_json_data:
         print json.dumps(my_json_data["my_data"])
Ajit Surendran
la source
4

J'ai écrit une petite fonction à cet effet. N'hésitez pas à réutiliser,

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

    return True
tabdiukov
la source