如何按键查找特定的json值?

2024-05-16 06:19:12 发布

您现在位置:Python中文网/ 问答频道 /正文

有这样一个json:

{
  "P1": "ss",
  "Id": 1234,
  "P2": {
      "P1": "cccc"
  },
  "P3": [
      {
          "P1": "aaa"
      }
  ]
}

如果不迭代所有json,我如何找到所有P1的值?

PS:P1可以是json中的任何位置。

如果没有方法可以做到这一点,您能告诉我如何遍历json吗?


Tags: 方法idjsonssccccpsp2p3
3条回答

正如我在other answer中所说的,我认为没有一种方法可以在不遍历整个结构的情况下找到与"P1"键关联的所有值。然而,当我看到@Mike Brennan关于另一个JSON相关问题的How to get string objects instead of Unicode from JSON?时,我想到了更好的方法

其基本思想是使用object_hook参数,而json.loads()只接受该参数来监视正在解码的内容并检查所需的值。注意:只有当表示是JSON ^{}(即用大括号{}括起来的东西)时,这才起作用,就像在示例JSON中一样。

import json

def find_values(id, json_repr):
    results = []

    def _decode_dict(a_dict):
        try: results.append(a_dict[id])
        except KeyError: pass
        return a_dict

    json.loads(json_repr, object_hook=_decode_dict)  # Return value ignored.
    return results

json_repr = '{"P1": "ss", "Id": 1234, "P2": {"P1": "cccc"}, "P3": [{"P1": "aaa"}]}'
print find_values('P1', json_repr)

输出:

[u'cccc', u'aaa', u'ss']

我对这个问题的态度会有所不同。

由于JSON不允许深度优先搜索,因此将JSON转换为Python对象,将其提供给XML解码器,然后提取要搜索的节点

from xml.dom.minidom import parseString
import json        
def bar(somejson, key):
    def val(node):
        # Searches for the next Element Node containing Value
        e = node.nextSibling
        while e and e.nodeType != e.ELEMENT_NODE:
            e = e.nextSibling
        return (e.getElementsByTagName('string')[0].firstChild.nodeValue if e 
                else None)
    # parse the JSON as XML
    foo_dom = parseString(xmlrpclib.dumps((json.loads(somejson),)))
    # and then search all the name tags which are P1's
    # and use the val user function to get the value
    return [val(node) for node in foo_dom.getElementsByTagName('name') 
            if node.firstChild.nodeValue in key]

bar(foo, 'P1')
[u'cccc', u'aaa', u'ss']
bar(foo, ('P1','P2'))
[u'cccc', u'cccc', u'aaa', u'ss']

前几天我也有同样的问题。最后,我搜索了整个对象,同时考虑了列表和听写。下面的代码片段允许您搜索多个键的第一个出现。

import json

def deep_search(needles, haystack):
    found = {}
    if type(needles) != type([]):
        needles = [needles]

    if type(haystack) == type(dict()):
        for needle in needles:
            if needle in haystack.keys():
                found[needle] = haystack[needle]
            elif len(haystack.keys()) > 0:
                for key in haystack.keys():
                    result = deep_search(needle, haystack[key])
                    if result:
                        for k, v in result.items():
                            found[k] = v
    elif type(haystack) == type([]):
        for node in haystack:
            result = deep_search(needles, node)
            if result:
                for k, v in result.items():
                    found[k] = v
    return found

deep_search(["P1", "P3"], json.loads(json_string))

它返回一个dict,其中键是搜索的键。Haystack应该已经是一个Python对象了,所以在将它传递给deep_search之前,必须先执行json.loads。

欢迎任何优化意见!

相关问题 更多 >