Anahtarın var olup olmadığını kontrol edin ve JSON dizisini Python kullanarak yineleyin


130

Aşağıdaki gibi Facebook gönderilerinden bir sürü JSON verisi var:

{"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 verileri yarı yapılandırılmıştır ve hepsi aynı değildir. Kodum aşağıdadır:

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

Kodun to_id'yi 1543 olarak yazdırmasını istiyorum, aksi takdirde 'null' yazdırmasını istiyorum

Bunu nasıl yapacağımdan emin değilim.

Yanıtlar:


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)

Çıktı:

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

6
Neden bu açık inkontroller yapıyor ve raiseeksiklerse? Sadece kontrol etmeden erişin ve tam olarak aynı davranışı elde edersiniz (a KeyErroryerine a ile hariç ValueError).
abarnert

101

Tek istediğiniz anahtarın var olup olmadığını kontrol etmekse

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

Anahtar için bir değer olup olmadığını kontrol etmek istiyorsanız

h.get('b') # returns None

Gerçek değer eksikse varsayılan bir değer döndür

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

{'a': 1, 'b': null} olması durumunda b için beklendiği gibi 'null' döndürür ve 'Varsayılan değer'
döndürmez

16

Bunun gibi şeyler için yardımcı yardımcı yardımcı yöntemler oluşturmak iyi bir uygulamadır, böylece öznitelik doğrulamasının mantığını değiştirmeniz gerektiğinde tek bir yerde olur ve kod takipçiler için daha okunabilir olur.

Örneğin, şurada bir yardımcı yöntem (veya JsonUtilsstatik yöntemlerle sınıf ) oluşturun json_utils.py:

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

ve sonra projenizde kullanın:

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

ÖNEMLİ NOT:

data.get(attribute) or default_valueBasitçe kullanmak yerine kullanmamın bir nedeni var data.get(attribute, default_value):

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

Benim uygulamalarımda 'null' değerine sahip özniteliği almak, özniteliği hiç almamakla aynıdır. Kullanımınız farklıysa, bunu değiştirmeniz gerekir.


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

Dene:

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

Veya, yazdırmak yerine kimlik eksik değerleri atlamak istiyorsanız 'null':

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

Yani:

>>> getTargetIds(jsonData)
to_id: 1543

Elbette gerçek hayatta, muhtemelen printher bir kimliği istemezsiniz , onları saklamak ve onlarla bir şeyler yapmak istersiniz , ama bu başka bir konu.



4

Bu amaçla küçük bir fonksiyon yazdım. Yeniden kullanmaktan çekinmeyin,

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

    return True
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.