Kiểm tra xem khóa có tồn tại không và lặp lại mảng JSON bằng Python


130

Tôi có một loạt dữ liệu JSON từ các bài đăng trên Facebook như dưới đây:

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

Dữ liệu JSON có cấu trúc bán cấu trúc và tất cả đều không giống nhau. Dưới đây là mã của tôi:

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

Tôi muốn mã để in to_id là 1543 khác in 'null'

Tôi không chắc chắn làm thế nào để làm điều này.

Câu trả lời:


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)

Đầu ra:

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

6
Tại sao phải inkiểm tra rõ ràng này và raisenếu chúng bị thiếu? Chỉ cần truy cập nó mà không cần kiểm tra, và bạn sẽ có chính xác hành vi tương tự (ngoại trừ KeyErrorthay vì a ValueError).
abarnert

99

Nếu tất cả những gì bạn muốn là kiểm tra xem khóa có tồn tại hay không

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

Nếu bạn muốn kiểm tra xem có giá trị nào cho khóa không

h.get('b') # returns None

Trả về giá trị mặc định nếu thiếu giá trị thực

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

sẽ trả về 'null' chứ không phải 'Giá trị mặc định' như mong đợi cho b trong trường hợp {'a': 1, 'b': null}
MikeL

16

Đó là một cách thực hành tốt để tạo các phương thức tiện ích của trình trợ giúp cho những thứ tương tự để bất cứ khi nào bạn cần thay đổi logic xác thực thuộc tính, nó sẽ ở một nơi và mã sẽ dễ đọc hơn cho người theo dõi.

Ví dụ: tạo một phương thức trợ giúp (hoặc lớp JsonUtilsvới các phương thức tĩnh) trong json_utils.py:

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

và sau đó sử dụng nó trong dự án của bạ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'))

LƯU Ý QUAN TRỌNG:

Có một lý do tôi đang sử dụng data.get(attribute) or default_valuethay vì đơn giản data.get(attribute, default_value):

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

Trong các ứng dụng của tôi, việc nhận thuộc tính có giá trị 'null' cũng giống như không nhận thuộc tính nào cả. Nếu cách sử dụng của bạn là khác nhau, bạn cần thay đổi điều này.


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

Thử nó:

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

Hoặc, nếu bạn chỉ muốn bỏ qua các giá trị thiếu id thay vì in 'null':

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

Vì thế:

>>> getTargetIds(jsonData)
to_id: 1543

Tất nhiên trong cuộc sống thực, có lẽ bạn không muốn printmỗi id, nhưng để lưu trữ chúng và làm điều gì đó với chúng, nhưng đó là một vấn đề khác.



4

Tôi đã viết một chức năng nhỏ cho mục đích này. Hãy thoải mái để tái sử dụng,

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

    return True
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.