从深度嵌套的JSON结构中提取值

4

这是我从其他地方获取的一个结构,即嵌套字典的列表:

{
    "foo_code": 404,
    "foo_rbody": {
        "query": {
            "info": {
                "acme_no": "444444",
                "road_runner": "123"
            },
            "error": "no_lunch",
            "message": "runner problem."
        }
    },
    "acme_no": "444444",
    "road_runner": "123",
    "xyzzy_code": 200,
    "xyzzy_rbody": {
        "api": {
            "items": [
                {
                    "desc": "OK",
                    "id": 198,
                    "acme_no": "789",
                    "road_runner": "123",
                    "params": {
                        "bicycle": "2wheel",
                        "willie": "hungry",
                        "height": "1",
                        "coyote_id": "1511111"
                    },
                    "activity": "TRAP",
                    "state": "active",
                    "status": 200,
                    "type": "chase"
                }
            ]
        }
    }
}

{
    "foo_code": 200,
    "foo_rbody": {
        "query": {
            "result": {
                "acme_no": "260060730303258",
                "road_runner": "123",
                "abyss": "26843545600"
            }
        }
    },
    "acme_no": "260060730303258",
    "road_runner": "123",
    "xyzzy_code": 200,
    "xyzzy_rbody": {
        "api": {
            "items": [
                {
                    "desc": "OK",
                    "id": 198,
                    "acme_no": "789",
                    "road_runner": "123",
                    "params": {
                        "bicycle": "2wheel",
                        "willie": "hungry",
                        "height": "1",
                        "coyote_id": "1511111"
                    },
                    "activity": "TRAP",
                    "state": "active",
                    "status": 200,
                    "type": "chase"
                }
            ]
        }
    }
}

要求不同的结构是不可能的(遗留API等)。

因此,我想知道是否有一些巧妙的方法可以从这样的结构中提取选定的值。

我考虑过的候选方案:

  • 展平特定的字典,建立复合键,如下所示:

    { "foo_rbody.query.info.acme_no": "444444", "foo_rbody.query.info.road_runner": "123", ... }

优点:通过一次访问获取每个值,如果没有可预测的键,则表示该结构不存在(您可能已经注意到,根据是否出现错误等不同,字典的结构可能不同)。

缺点:如何处理列表?

  • 使用某个递归函数进行连续的键查找,例如按“foo_rbody”、然后按“query”、“info”等查找。

还有更好的方案吗?

4个回答

9
您可以尝试使用以下相对简单的函数来访问嵌套属性:
import re

def get_path(dct, path):
    for i, p in re.findall(r'(\d+)|(\w+)', path):
        dct = dct[p or int(i)]
    return dct

使用方法:

value = get_path(data, "xyzzy_rbody.api.items[0].params.bicycle")

1
简单、非递归、紧凑。为什么我没想到这样的东西呢?哦,算了。 - LetMeSOThat4U

2
也许我在这篇文章中回答的byPath函数可以帮助你。请注意保留HTML标签。

1
您可以创建自己的路径机制,然后使用路径查询复杂的字典。例如:
  • /:获取根对象
  • /key:获取root_object['key']的值,例如/foo_code --> 404
  • /key/key:嵌套:/foo_rbody/query/info/acme_no --> 444444
  • /key[i]:获取列表中的第i个元素,例如/xyzzy_rbody/api/items[0]/desc --> "OK"
路径还可以返回一个字典,您可以在其中运行更多的查询等等。
这个实现起来也很容易实现递归。

1

Pynq很酷,谢谢!我不确定我会使用它(在这里似乎有些过度),但拥有这样的工具非常好。 - LetMeSOThat4U

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接