[英]Python how to access specific json dictionary value by chaining the 'key'
If I have the following Json:如果我有以下 Json:
{
"a": {
"b" : {
"c" : "value"
}
}
}
This is loaded into my object (obj) via json.load()这是通过 json.load() 加载到我的对象 (obj) 中的
Then I have another variable which is然后我有另一个变量是
path = "a.b.c"
To access the value of 'c' in the json, I would typically do:要访问 json 中 'c' 的值,我通常会这样做:
obj["a"]["b"]["c"]
However I would like to leverage the 'path' variable, and do something like this:但是我想利用“路径”变量,并做这样的事情:
obj[path]
Is this possible?这可能吗? How can this be achieved
如何实现
You could write a function that takes both the JSON data and the path as arguments.您可以编写一个将 JSON 数据和路径都作为参数的函数。 It can iterate through each key in the path (separated by
.
) and traverse through the JSON that way.它可以遍历路径中的每个键(由
.
分隔)并以这种方式遍历 JSON。
def json_from_path(data: dict, path: str):
for key in path.split('.'):
data = data[key]
return data
It's possible to do so using a combination of operator.getitem
and functools.reduce
:可以使用
operator.getitem
和functools.reduce
的组合来做到这一点:
>>> from functools import reduce
>>> from operator import getitem
>>> dct = {'a': {'b': {'c': 'value'}}}
>>> reduce(getitem, "a.b.c".split("."), dct)
'value'
The way this works is that reduce will initially invoke getitem
using dct
and the first item from the "abc".split()
ie "a"
and then the result of it is then passed to getitem
in next iteration but this time with "b"
and so on...它的工作方式是,reduce 最初将使用
dct
调用getitem
和"abc".split()
即"a"
,然后在下一次迭代中将其结果传递给getitem
,但这次使用"b"
等等……
>>> getitem(dct, "a")
{'b': {'c': 'value'}}
>>> getitem(getitem(dct, "a"), "b")
{'c': 'value'}
>>> getitem(getitem(getitem(dct, "a"), "b"), "c")
'value'
And getitem
in itself works like: getitem
本身的工作方式如下:
>>> getitem?
Signature: getitem(a, b, /)
Docstring: Same as a[b].
Type: builtin_function_or_method
It's a third-party installation, but the jq
package lets you traverse data structures using the jq
filter language.它是第三方安装,但
jq
包允许您使用jq
过滤器语言遍历数据结构。
>>> import jq
>>> d = {"a": {"b": {"c": "value"}}}
>>> jq.compile(".a.b.c").input(d).first()
'value'
(Note that .
has to precede each key, rather than simply separating the keys, in the path.) (请注意,
.
必须在路径中的每个键之前,而不是简单地分隔键。)
This might be a little beyond the scope of the question, but you can always subclass the dict
type and overwrite the __getitem__
method to get the result you are looking for.这可能有点超出问题的范围,但您始终可以将
dict
类型子类化并覆盖__getitem__
方法以获得您正在寻找的结果。
This is the way that you could actually achieve the result the OP is asking for with the syntax used by the OP.这是您可以使用 OP 使用的语法实际实现 OP 要求的结果的方式。
For example:例如:
class Dict(dict):
def __getitem__(self, val):
try: return super().__getitem__(val)
except KeyError:
keys = val.split(".")
value = super().__getitem__(keys[0])
d = Dict(value)
return d['.'.join(keys[1:])]
Then it's as simple as:然后就这么简单:
path = 'a.b.c'
obj = Dict({"a": {"b" : {"c" : "value"}}})
result = obj[path]
print(result)
OUTPUT输出
value
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.