[英]How to find a particular JSON value by key?
有一個像這樣的 JSON:
{
"P1": "ss",
"Id": 1234,
"P2": {
"P1": "cccc"
},
"P3": [
{
"P1": "aaa"
}
]
}
如何在不迭代所有 JSON 的情況下找到所有P1
的值?
PS: P1
可以在 JSON 中的任何位置。
如果沒有方法可以做到這一點,你能告訴我如何遍歷 JSON 嗎?
正如我在其他答案中所說,我認為沒有辦法在不遍歷整個結構的情況下找到與"P1"
鍵關聯的所有值。 不過我已經想出更好的方法來做到這一點它來找我一邊看着@Mike布倫南的回答另一個JSON相關的問題, 如何獲得字符串從JSON對象,而不是Unicode的?
基本思想是使用json.loads()
接受的object_hook
參數來觀察正在解碼的內容並檢查尋找的值。
注意:這僅在表示是 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']
前幾天我遇到了同樣的問題。 我最終只是搜索了整個對象並考慮了列表和字典。 以下片段允許您搜索多個鍵的第一次出現。
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))
它返回一個字典,其中的鍵是搜索的鍵。 Haystack 應該已經是一個 Python 對象,所以你必須在將它傳遞給 deep_search 之前執行 json.loads。
歡迎任何優化意見!
我對這個問題的處理方法會有所不同。
由於 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']
使用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)
將 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 是字符串)
示例代碼忽略數組。 添加它作為練習。
記住 json 只是一個字符串,使用帶有前瞻和后視的正則表達式可以非常快速地完成這項任務。
通常,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']
我認為沒有任何方法可以在不迭代整個結構的情況下找到與 P1 相關的所有值。 這是一種遞歸方法,首先將 JSON 對象反序列化為等效的 Python 對象。 為了簡化事情,大部分工作是通過遞歸私有嵌套函數完成的。
import json
try:
STRING_TYPE = basestring
except NameError:
STRING_TYPE = str # Python 3
def find_values(id, obj):
results = []
def _find_values(id, obj):
try:
for key, value in obj.items(): # dict?
if key == id:
results.append(value)
elif not isinstance(value, STRING_TYPE):
_find_values(id, value)
except AttributeError:
pass
try:
for item in obj: # iterable?
if not isinstance(item, STRING_TYPE):
_find_values(id, item)
except TypeError:
pass
if not isinstance(obj, STRING_TYPE):
_find_values(id, obj)
return results
json_repr = '{"P1": "ss", "Id": 1234, "P2": {"P1": "cccc"}, "P3": [{"P1": "aaa"}]}'
obj = json.loads(json_repr)
print(find_values('P1', obj))
您還可以使用生成器在 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
這個問題很老,但沒有100%的答案,所以這是我的解決方案:
它能做什么:
建議:
@staticmethod
def search_into_json_myversion(jsondata, searchkey, parentkeyname: str = None) -> list:
found = []
if type(jsondata) is list:
for element in jsondata:
val = Tools.search_into_json_myversion(element, searchkey, parentkeyname=parentkeyname)
if len(val) != 0:
found = found + val
elif type(jsondata) is dict:
if searchkey in jsondata.keys():
pathkey = parentkeyname + '->' + searchkey if parentkeyname != None else searchkey
found.append({pathkey: jsondata[searchkey]})
else:
for key, value in jsondata.items():
val = Tools.search_into_json_myversion(value, searchkey, parentkeyname=key)
if len(val) != 0:
found = found + val
return found
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.