如何通过键找到特定的json值?

lic*_*gwu 25 python search json

有一个像这样的json:

{
  "P1": "ss",
  "Id": 1234,
  "P2": {
      "P1": "cccc"
  },
  "P3": [
      {
          "P1": "aaa"
      }
  ]
}
Run Code Online (Sandbox Code Playgroud)

P1如果没有迭代所有json,我怎么能找到所有的价值?

PS:P1可以在json的任何地方.

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

mar*_*eau 20

正如我在其他答案中所说,我认为没有办法找到与"P1"密钥相关的所有值而不迭代整个结构.然而,我已经想出了更好的方法来做到这一点,当我看到一个不同的问题的接受的答案如何从JSON获取字符串对象而不是Unicode?

基本思想是使用仅接受的object_hook参数json.loads()来观察正在解码的内容并检查所寻求的值.注意:这仅在表示为JSON object(即大括号括起来的东西{})时才有效,如示例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)
Run Code Online (Sandbox Code Playgroud)

输出:

[u'cccc', u'aaa', u'ss']
Run Code Online (Sandbox Code Playgroud)


Sea*_*han 12

前几天我遇到了同样的问题.我结束了搜索整个对象,并考虑了列表和dicts.以下代码段允许您搜索多个键的第一个匹配项.

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))
Run Code Online (Sandbox Code Playgroud)

它返回一个dict,键是搜索的键.Haystack预计已经是一个Python对象了,所以在将它传递给deep_search之前你必须先做json.loads.

欢迎任何评论优化!


Abh*_*jit 11

我解决这个问题的方法会有所不同.

由于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']
Run Code Online (Sandbox Code Playgroud)


Mal*_*lio 7

将JSON转换为Python并递归搜索是迄今为止最简单的:

def findall(v, k):
  if type(v) == type({}):
     for k1 in v:
         if k1 == k:
            print v[k1]
         findall(v[k1], k)

findall(json.loads(a), 'P1')
Run Code Online (Sandbox Code Playgroud)

(其中a是字符串)

示例代码忽略了数组.添加它作为练习.


jdo*_*dot 7

使用json的JSON到Python对象转换,然后要通过递归效果最好.这个例子包括通过列表去.

import json
def get_all(myjson, key):
    if type(myjson) == str:
        myjson = json.loads(myjson)
    if type(myjson) is dict:
        for jsonkey in myjson:
            if type(myjson[jsonkey]) in (list, dict):
                get_all(myjson[jsonkey], key)
            elif jsonkey == key:
                print myjson[jsonkey]
    elif type(myjson) is list:
        for item in myjson:
            if type(item) in (list, dict):
                get_all(item, key)
Run Code Online (Sandbox Code Playgroud)


小智 5

请记住,json只是一个字符串,使用具有alook-ahead和look-behind的正则表达式可以非常快速地完成此任务。

通常,json是从对外部api的请求中提取的,因此包含了演示如何工作的代码,但已将其注释掉。

import re
#import requests
#import json

#r1 = requests.get( ... url to some api ...)
#JSON = str(json.loads(r1.text))
JSON = """
 {
  "P1": "ss",
  "Id": 1234,
  "P2": {
      "P1": "cccc"
  },
  "P3": [
     {
          "P1": "aaa"
     }
  ]
 }
"""
rex1  = re.compile('(?<=\"P1\": \")[a-zA-Z_\- ]+(?=\")')
rex2 = rex1.findall(JSON)  
print(rex2)

#['ss', 'cccc', 'aaa']
Run Code Online (Sandbox Code Playgroud)