Разбор json и поиск по нему - PullRequest
       28

Разбор json и поиск по нему

17 голосов
/ 05 декабря 2011

У меня есть этот код

import json
from pprint import pprint
json_data=open('bookmarks.json')
jdata = json.load(json_data)
pprint (jdata)
json_data.close()

Как я могу найти по нему u'uri': u'http:?

Ответы [ 5 ]

22 голосов
/ 05 декабря 2011

Поскольку json.loads просто возвращает dict, вы можете использовать операторы, которые применяются к dict:

>>> jdata = json.load('{"uri": "http:", "foo", "bar"}')
>>> 'uri' in jdata       # Check if 'uri' is in jdata's keys
True
>>> jdata['uri']         # Will return the value belonging to the key 'uri'
u'http:'

Изменить: чтобы дать представление о том, как циклически перебирать данные, рассмотрим следующий пример:

>>> import json
>>> jdata = json.loads(open ('bookmarks.json').read())
>>> for c in jdata['children'][0]['children']:
...     print 'Title: {}, URI: {}'.format(c.get('title', 'No title'),
                                          c.get('uri', 'No uri'))
...
Title: Recently Bookmarked, URI: place:folder=BOOKMARKS_MENU(...)
Title: Recent Tags, URI: place:sort=14&type=6&maxResults=10&queryType=1
Title: , URI: No uri
Title: Mozilla Firefox, URI: No uri

Проверка структуры данных jdata позволит вам перемещаться по ней по своему усмотрению. Звонок pprint, который у вас уже есть, является хорошей отправной точкой для этого.

Edit2: еще одна попытка. Получается файл, который вы упомянули в списке словарей. При этом, я думаю, вы сможете адаптировать его к вашим потребностям.

>>> def build_structure(data, d=[]):
...     if 'children' in data:
...         for c in data['children']:
...             d.append({'title': c.get('title', 'No title'),
...                                      'uri': c.get('uri', None)})
...             build_structure(c, d)
...     return d
...
>>> pprint.pprint(build_structure(jdata))
[{'title': u'Bookmarks Menu', 'uri': None},
 {'title': u'Recently Bookmarked',
  'uri':   u'place:folder=BOOKMARKS_MENU&folder=UNFILED_BOOKMARKS&(...)'},
 {'title': u'Recent Tags',
  'uri':   u'place:sort=14&type=6&maxResults=10&queryType=1'},
 {'title': u'', 'uri': None},
 {'title': u'Mozilla Firefox', 'uri': None},
 {'title': u'Help and Tutorials',
  'uri':   u'http://www.mozilla.com/en-US/firefox/help/'},
 (...)
}]

Чтобы потом "найти в нем u'uri': u'http:'" , сделайте что-то вроде этого:

for c in build_structure(jdata):
    if c['uri'].startswith('http:'):
        print 'Started with http'
16 голосов
/ 06 января 2017

ObjectPath - это библиотека, которая предоставляет возможность запрашивать JSON и вложенные структуры диктов и списков. Например, вы можете искать все атрибуты с именем "foo" независимо от их глубины, используя $..foo.

Хотя документация посвящена интерфейсу командной строки, вы можете выполнять запросы программно, используя внутреннюю часть пакета Python. В приведенном ниже примере предполагается, что вы уже загрузили данные в структуры данных Python (dicts & lists). Если вы начинаете с JSON-файла или строки, вам просто нужно сначала использовать load или loads из модуля json .

import objectpath

data = [
    {'foo': 1, 'bar': 'a'},
    {'foo': 2, 'bar': 'b'},
    {'NoFooHere': 2, 'bar': 'c'},
    {'foo': 3, 'bar': 'd'},
]

tree_obj = objectpath.Tree(data)

tuple(tree_obj.execute('$..foo'))
# returns: (1, 2, 3)

Обратите внимание, что он просто пропустил элементы, в которых отсутствовал атрибут "foo", например, третий элемент в списке. Вы также можете выполнять гораздо более сложные запросы, что делает ObjectPath удобным для глубоко вложенных структур (например, для нахождения где x имеет y с z: $.x.y.z). Я отсылаю вас к документации и учебник для получения дополнительной информации.

1 голос
/ 02 апреля 2017

Кажется, в JSON есть опечатка (отсутствует двоеточие), предоставленная jro.

Правильный синтаксис: jdata = json.load ('{"uri": "http:", "foo":" bar "} ')

Это прояснилось для меня при игре с кодом.

0 голосов
/ 09 июня 2017

Функции для поиска и печати диктовок, например, JSON.* сделано в python 3

Поиск:

def pretty_search(dict_or_list, key_to_search, search_for_first_only=False):
    """
    Give it a dict or a list of dicts and a dict key (to get values of),
    it will search through it and all containing dicts and arrays
    for all values of dict key you gave, and will return you set of them
    unless you wont specify search_for_first_only=True

    :param dict_or_list: 
    :param key_to_search: 
    :param search_for_first_only: 
    :return: 
    """
    search_result = set()
    if isinstance(dict_or_list, dict):
        for key in dict_or_list:
            key_value = dict_or_list[key]
            if key == key_to_search:
                if search_for_first_only:
                    return key_value
                else:
                    search_result.add(key_value)
            if isinstance(key_value, dict) or isinstance(key_value, list) or isinstance(key_value, set):
                _search_result = pretty_search(key_value, key_to_search, search_for_first_only)
                if _search_result and search_for_first_only:
                    return _search_result
                elif _search_result:
                    for result in _search_result:
                        search_result.add(result)
    elif isinstance(dict_or_list, list) or isinstance(dict_or_list, set):
        for element in dict_or_list:
            if isinstance(element, list) or isinstance(element, set) or isinstance(element, dict):
                _search_result = pretty_search(element, key_to_search, search_result)
                if _search_result and search_for_first_only:
                    return _search_result
                elif _search_result:
                    for result in _search_result:
                        search_result.add(result)
    return search_result if search_result else None

Печать:

def pretty_print(dict_or_list, print_spaces=0):
    """
    Give it a dict key (to get values of),
    it will return you a pretty for print version
    of a dict or a list of dicts you gave.

    :param dict_or_list: 
    :param print_spaces: 
    :return: 
    """
    pretty_text = ""
    if isinstance(dict_or_list, dict):
        for key in dict_or_list:
            key_value = dict_or_list[key]
            if isinstance(key_value, dict):
                key_value = pretty_print(key_value, print_spaces + 1)
                pretty_text += "\t" * print_spaces + "{}:\n{}\n".format(key, key_value)
            elif isinstance(key_value, list) or isinstance(key_value, set):
                pretty_text += "\t" * print_spaces + "{}:\n".format(key)
                for element in key_value:
                    if isinstance(element, dict) or isinstance(element, list) or isinstance(element, set):
                        pretty_text += pretty_print(element, print_spaces + 1)
                    else:
                        pretty_text += "\t" * (print_spaces + 1) + "{}\n".format(element)
            else:
                pretty_text += "\t" * print_spaces + "{}: {}\n".format(key, key_value)
    elif isinstance(dict_or_list, list) or isinstance(dict_or_list, set):
        for element in dict_or_list:
            if isinstance(element, dict) or isinstance(element, list) or isinstance(element, set):
                pretty_text += pretty_print(element, print_spaces + 1)
            else:
                pretty_text += "\t" * print_spaces + "{}\n".format(element)
    else:
        pretty_text += str(dict_or_list)
    if print_spaces == 0:
        print(pretty_text)
    return pretty_text
0 голосов
/ 05 декабря 2011

Вы можете использовать jsonpipe , если вам просто нужен вывод (и удобнее с командной строкой):

cat bookmarks.json | jsonpipe |grep uri
...