1

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

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

4 回答 4

2

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

于 2012-09-05T23:46:41.650 回答
1

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

是的,有很多方法。不幸的是,您没有指定您正在寻找的答案。

“就模式而言是唯一的”(我的术语)如下:例如,如果您有多个带有键 Foo.bar 的 Foo 字典,那么它仍然是唯一的。不同的是,如果你有 Foo 对象和 Foo.bar,Baz 对象和 Baz.bar:搜索{... baz:...}将返回不同类型的对象。

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

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

于 2012-09-06T00:44:23.723 回答
0

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

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()它,如我上面所示。如果需要,您也可以将其转换为 a list()

于 2012-09-05T23:26:51.590 回答
0

不,您需要知道格式,否则您必须手动遍历其中的所有内容。

于 2012-09-05T23:34:06.563 回答