首页 > 解决方案 > json_normalize:从数组中的对象访问数据

问题描述

我需要从 JSON“列表”中提取大量信息到 pandas 数据框。

考虑以下 JSON 文件:

{
    "List": [
        {
            "Name": "xml",
            "CreateTime": "2020-11-13T10:44:20",
            "Descriptor": {
                "Location": "some/url",
                ...
            }
            "Permissions": [
                {
                    "Principal": {
                        "Identifier": "ALLOWED_PRINCIPALS"
                    },
                    "Example": [
                        "ALL"
                    ]
                }
            ],
        },
        ...
    ]
}

我正在使用以下 python 代码从此 json 中提取信息到 pandas 数据帧:

for List in response['List']:
    df = pd.json_normalize(response['List'])
    df = df.reindex(columns=['Name','CreateTime','Descriptor.Location','Permissions[Identifier]'])

前三列填充没有问题,但我无法访问存储在

其他列填充数据框,而我只为标识符和示例获取 NULL。我也尝试过指定:Permissions['Identifier'],但在我的示例中这将是一个语法错误。

第二个例子:嵌套库中的一个数组

{
    "Table": [
        {
            "TableName": "data",
            "Descriptor": {
                "Columns": [
                    {
                        "Name": "category",
                        "Type": "string"
                    },
                    {
                        "Name": "author",
                        "Type": "string"
                    },
                    {
                        "Name": "title",
                        "Type": "string"
                    },
                    ...

在这种情况下,我试图访问“描述符”->“列”下的多个“名称”列的值

在第一部分使用 Jonathan Leon 的解决方案,我为第二个示例尝试了以下代码:

for DatabaseList in db_response['Table']:
    df = pd.json_normalize(db_response['Table'], record_path=['Descriptor.Columns'], 
                        meta=['TableName', ['Descriptor.Columns']])
    df = df.reindex(columns=['TableName','Name'])
    

不幸的是,这样定义记录路径是不可能的。我必须以某种方式定义一个嵌套的记录路径来访问“列”中的数据。

我还必须将 record_prefix 添加到 json_normalize 部分,因为有多个“名称”列。

在我的示例中,使用 python 代码访问库和数组数据的正确语法是什么?

标签: pandas

解决方案


根据您提供的截断列表,这应该可以帮助您入门。json_normalize 的文档在这里。对于多层列表,您可能需要循环和连接数据帧。

df = pd.json_normalize(response['List'], record_path=['Permissions'], meta=['Name', 'CreateTime', ['Descriptor', 'Location']],
                        meta_prefix='', record_prefix='')
df = df.reindex(columns=['Name','CreateTime','Descriptor.Location','Principal.Identifier', 'Example'])
df.rename(columns={'Principal.Identifier':'Permissions.Identifier'})
pd.concat([ df, df['Example'].apply(pd.Series)], axis = 1)

输出(我修改了示例列表以说明扩展值):

  Name           CreateTime Descriptor.Location Principal.Identifier      Example    0     1
0  xml  2020-11-13T10:44:20            some/url   ALLOWED_PRINCIPALS  [ALL, SOME]  ALL  SOME

推荐阅读