it-roy-ru.com

Проверьте, существует ли ключ, и итерируйте массив JSON, используя Python

У меня есть куча данных JSON из постов Facebook, как показано ниже:

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

Данные JSON полуструктурированы, и все они не одинаковы. Ниже мой код:

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":...}]}

Я хочу, чтобы код напечатал to_id как 1543, иначе выведите 'null'

Я не уверен, как это сделать.

Спасибо!

94
pravi
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)

Результат:

In [9]: getTargetIds(s)
to_id: 1543
120
inspectorG4dget

Если все, что вы хотите, это проверить, существует ли ключ или нет

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

Если вы хотите проверить, есть ли значение для ключа

h.get('b') # returns None

Вернуть значение по умолчанию, если фактическое значение отсутствует

h.get('b', 'Default value')
69
athap

Рекомендуется создавать вспомогательные служебные методы для подобных вещей, чтобы всякий раз, когда вам нужно было изменить логику проверки атрибута, она находилась в одном месте, и код был бы более читабельным для последователей.

Например, создайте вспомогательный метод (или класс JsonUtils со статическими методами) в json_utils.py:

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

а затем использовать его в своем проекте:

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

ВАЖНОЕ ПРИМЕЧАНИЕ:

Есть причина, по которой я использую data.get(attribute) or default_value вместо просто data.get(attribute, default_value):

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

В моих приложениях получение атрибута со значением 'null' - это то же самое, что вообще не получать атрибут. Если ваше использование отличается, вы должны изменить это.

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

Попытайся:

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

Или, если вы просто хотите пропустить пропущенные значения вместо того, чтобы печатать 'null':

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

Так:

>>> getTargetIds(jsonData)
to_id: 1543

Конечно, в реальной жизни вы, вероятно, не хотите print каждого идентификатора, но сохраняете их и что-то с ними делаете, но это другая проблема.

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