简体   繁体   English

Python如何通过链接'key'来访问特定的json字典值

[英]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 can split the path on dot and use reduce to get the nested value.您可以拆分点上的路径并使用reduce来获取嵌套值。

from functools import reduce
d = {'a':{'b':{'c':'value'}}}
path = "a.b.c"
val = reduce(lambda o, k: o[k], path.split("."), d)
print(val)

Demo演示

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.getitemfunctools.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM