解析 JSON 并进行搜索

24 投票
5 回答
128425 浏览
提问于 2025-04-17 07:43

我有这段代码:

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 个回答

1

看起来jro提供的JSON字典里有个错别字(缺少冒号)。

正确的写法应该是:

jdata = json.load('{"uri": "http:", "foo": "bar"}')

当我在玩这个代码的时候,这个问题就解决了。

35

ObjectPath 是一个库,它可以帮助你查询 JSON 数据以及嵌套的字典和列表结构。比如,你可以用 $..foo 来查找所有叫 "foo" 的属性,不管它们在多深的层级。

虽然文档主要讲的是命令行界面,但你也可以通过这个库的 Python 内部功能来编程执行查询。下面的例子假设你已经把数据加载到 Python 的数据结构中(字典和列表)。如果你是从 JSON 文件或字符串开始的,首先需要使用 loadloadsjson 模块 来加载数据。

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,y 中有 z 的情况:$.x.y.z)。如果想了解更多信息,可以参考 文档教程

29

因为 json.loads 只是返回一个字典,所以你可以使用适用于字典的操作符:

>>> 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 调用是一个很好的起点。

补充2:这是另一个尝试。这个方法可以把你提到的文件转成一个字典列表。这样的话,我觉得你应该能根据自己的需求进行调整。

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

撰写回答