34

次のような JSON があります。

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

P1すべての JSON を反復せずにall の値を見つけるにはどうすればよいですか?

PS: JSON のどこP1にでもかまいません。

これを行う方法がない場合、JSON を反復処理する方法を教えてもらえますか?

4

8 に答える 8

26

他の回答で述べたように"P1"、構造全体を反復せずにキーに関連付けられたすべての値を見つける方法はないと思います。ただし、別のJSON関連の質問How to get string objects instead of Unicode from JSON?

基本的な考え方は、デコードされているものを監視し、求められている値を確認するためだけに受け入れるobject_hookパラメーターを使用することです。json.loads()

注:これは、サンプルのように、表現が JSON (中括弧objectで囲まれたもの) の場合にのみ機能します。 {}

from __future__ import print_function
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))

(Python 3) 出力:

['cccc', 'aaa', 'ss']
于 2012-12-27T18:46:59.090 に答える
13

先日、同じ問題が発生しました。オブジェクト全体を検索するだけで終わり、リストと辞書の両方を説明しました。次のスニペットを使用すると、複数のキーの最初の出現を検索できます。

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 を実行する必要があります。

最適化のためのコメントは大歓迎です!

于 2012-12-27T03:53:19.160 に答える
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']
于 2012-12-27T06:08:56.710 に答える
10

を使用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)
于 2012-12-27T03:47:40.420 に答える
6

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

(a は文字列)

サンプル コードは配列を無視します。それを追加することは演習として残されています。

于 2012-12-27T03:25:46.210 に答える
1

ジェネレーターを使用して、json.load() の後にオブジェクトを検索することもできます。

私の回答のコード例: https://stackoverflow.com/a/39016088/5250939

def item_generator(json_input, lookup_key):
    if isinstance(json_input, dict):
        for k, v in json_input.iteritems():
            if k == lookup_key:
                yield v
            else:
                for child_val in item_generator(v, lookup_key):
                    yield child_val
    elif isinstance(json_input, list):
        for item in json_input:
            for item_val in item_generator(item, lookup_key):
                yield item_val
于 2016-08-18T11:39:17.907 に答える