使用未知的嵌套位置访问字典中的变量

时间:2012-09-05 23:10:26

标签: python json

我有一个JSON文件,我想使用python查询它。但是,我不知道变量的嵌套位置。例如。要查询下面加载到python中的JSON对象并调用'data',我可以执行以下操作:

data['experiments']['initial_ns']['icdat']

但是,这假设我知道icdat变量位于initial_ns下面的experiments下方。不幸的是,我没有这些信息,JSON结构也可能在未来发生变化。是否有一个更简单的变量来访问JSON字符串中的变量而不显式指定整个结构?

感谢!!!

{
    "experiments": [
        {
            "management": {
                "events": [
                    {
                        "date": "19122", 
                        "timp": "TI3", 
                        "eve": "tage"
                    }
                ]
            }, 
            "initial_ns": {
                "icpcr": "MZ", 
                "icdat": "1922"
            }, 
            "observed": {
                "mdat": "19403", 
                "time_series": [
                    {
                        "date": "198423", 
                        "etac": "0"
                    }
                ], 
                "adat": "190218"
            }, 
            "local_name": "lhi", 
            "exname": "SE", 
            "exp_dur": "1"
        }
    ]
}

4 个答案:

答案 0 :(得分:2)

查看jsonpath模块。 http://goessner.net/articles/JsonPath/。我认为搜索字符串$ .. icdat将符合您的需求。

答案 1 :(得分:1)

  

“... 没有明确指定整个结构?

是的,有很多方法。很遗憾,您尚未指定要查找的答案。

“在模式方面是独一无二的”(我的术语)如下:如果你有多个Foo字典和密钥Foo.bar,那么它仍然是唯一的。不唯一的是,如果你有Foo.bar的Foo对象和Baz.bar的Baz对象:搜索{... baz:...}会返回不同类型的对象。

如果密钥在架构方面是唯一的,则可以搜索整个树。您可以通过缓存字典中的所有键值对以便以后使用来加快速度(因此操作是O(1)“即时”摊销成本,因为您无论如何都需要遍历整个数据结构来解析它!) 。如果您想要返回多组对象,这甚至可以工作:使用cache = collections.defaultdict(set),当您预处理要缓存的项目时,请执行cache[key].add(value)

如果密钥在模式方面不是唯一的,那么您将需要对路径进行合理的猜测并提供一些部分信息,根据Hans Then的答案利用率JsonPath:https://stackoverflow.com/a/12291240/711085(或者,更改模式)

答案 2 :(得分:0)

您可以编写一个函数来递归搜索给定键的嵌套容器,类似于XML DOM解析器中的findElementByID()

def find_key(json, key):
    if isinstance(json, dict):
        if key in json:
            yield json[key]
    if isinstance(json, (dict, list)):
        for value in (json.itervalues() if isinstance(json, dict) else json):
            if isinstance(value, (dict, list)):
                for item in find_key(value, key):
                    yield item

>>> next(items_by_key(data, "icdat"))
'1922'

由于可以在文档中的多个位置找到相同的密钥,因此实际上将其写为生成器。您可以迭代结果以获取所有值,或者,如果您只想要第一个(或知道它是唯一的),请使用next(),如上所示。如果需要,您也可以将其转换为list()

答案 3 :(得分:0)

没有。您需要知道格式,或者您必须手动循环其中的所有内容。