【问题标题】:Fetch nested vales from JSON - python从 JSON 中获取嵌套值 - python
【发布时间】:2020-04-30 08:16:36
【问题描述】:

我有如下代码,我需要 status 和 policy workflow name(即星期二)以及具有以下 2 个条件的输出 -

1- 如果 clientHostname 匹配 xyz 删除该行 2- 如果状态为 [Aborted] 将其更改为 [Failed]

import json
import requests
import pandas as pd
from pandas.io.json import json_normalize
import ast
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
pd.set_option('display.width', 100)

a = [{'attributes': [{'key': '*policy action jobid', 'values': ['289903']}, {'key': '*policy action name', 'values': ['backup']}, {'key': '*policy name', 'values': ['Daily_Backups']}, {'key': '*policy workflow name', 'values': ['tuesday']}, {'key': 'clone retention policy', 'values': ['   504:   5:  34']}, {'key': 'group', 'values': ['tuesday']}, {'key': 'saveset features', 'values': ['CLIENT_SAVETIME']}], 'browseTime': '2020-05-19T23:57:41+08:00', 'clientHostname': 'xyz.com', 'clientId': '7d391c52-00000004-5cda459d-5c1', 'creationTime': '2020-04-28T21:29:25+08:00', 'fileCount': 0, 'id': '1eb1', 'instances': [], 'level': 'Full', 'links': [{'href': 'https://iservera/backups/1ec1', 'rel': 'item'}], 'name': '/abc', 'retentionTime': '2020-05-19T23:57:41+08:00', 'saveTime': '2020-04-28T21:27:07+08:00', 'shortId': '2177', 'size': {'unit': 'Byte', 'value': 0}, 'type': 'File'}, {'attributes': [{'key': '*policy action jobid', 'values': ['2803']}, {'key': '*policy action name', 'values': ['backup: 1589']}, {'key': '*policy name', 'values': ['Daily_Backups: 159']}, {'key': '*policy workflow name', 'values': ['tuesday: 1588079529']}, {'key': '*ss clone retention', 'values': ['          1588079529:          1588079590:   1824409']}, {'key': 'group', 'values': ['tuesday']}, {'key': 'saveset features', 'values': ['CLIENT_SAVETIME']}], 'browseTime': '2020-05-19T23:57:42+08:00', 'clientHostname': 'abc.com', 'clientId': 'ec3dc1', 'completionTime': '2020-04-28T21:29:47+08:00', 'creationTime': '2020-04-28T21:13:10+08:00', 'fileCount': 0, 'id': 'cc1', 'instances': [{'clone': False, 'id': '1588079529', 'status': 'Aborted', 'volumeIds': ['245614341']}], 'level': 'Full', 'links': [{'href': 'https://abc/backups/c771', 'rel': 'item'}], 'name': '/xyz', 'retentionTime': '2020-05-19T23:57:42+08:00', 'saveTime': '2020-04-28T21:10:53+08:00', 'shortId': '2141727718', 'size': {'unit': 'Byte', 'value': 36264099844}, 'type': 'NDMP'}]
df = json_normalize(a)
a = df[['clientHostname','completionTime','size.value','type','fileCount']]
print(a)

当前输出为:

clientHostname             completionTime   size.value  type  fileCount
0        xyz.com                        NaN            0  File          0
1        abc.com  2020-04-28T21:29:47+08:00  36264099844  NDMP          0

预期输出是:

clientHostname             completionTime   size.value  type  fileCount  status Policy
1        abc.com  2020-04-28T21:29:47+08:00  36264099844  NDMP          0 [Failed] tuesday

【问题讨论】:

  • 请添加预期清晰的输出
  • 附加预期输出。

标签: python json python-3.x pandas


【解决方案1】:

我将使用库 jmespath 来遍历 json 数据:

要访问密钥,请使用.;要访问列表,请使用 [] 表示法。

import jmespath
expression = jmespath.compile("""
                              [].
                               {clientHostname:clientHostname,
                                completionTime:completionTime,
                                "size.value":size.value,
                                type:type,
                                fileCount:fileCount,
                                status:instances[].status,
                                Policy:attributes[?key==`*policy workflow name`].values[]}
                               """)
res = expression.search(a)
res

[{'clientHostname': 'xyz.com',
  'completionTime': None,
  'size.value': 0,
  'type': 'File',
  'fileCount': 0,
  'status': [],
  'Policy': ['tuesday']},
 {'clientHostname': 'abc.com',
  'completionTime': '2020-04-28T21:29:47+08:00',
  'size.value': 36264099844,
  'type': 'NDMP',
  'fileCount': 0,
  'status': ['Aborted'],
  'Policy': ['tuesday: 1588079529']}]

进行一些清理以适应您的用例:

new = []
for entry in res:
    if "xyz" in entry['clientHostname'] :
        continue
    new.append(entry)

for ent in new:
    ent['Policy'] = ent['Policy'][0].split(':')[0]
    if ent['status'] == ["Aborted"]:
        ent['status'] = ["Failed"]

new

[{'clientHostname': 'abc.com',
  'completionTime': '2020-04-28T21:29:47+08:00',
  'size.value': 36264099844,
  'type': 'NDMP',
  'fileCount': 0,
  'status': ['Failed'],
  'Policy': 'tuesday'}]

 pd.DataFrame(new)


    clientHostname  completionTime  size.value  type    fileCount   status  Policy
0   abc.com 2020-04-28T21:29:47+08:00   36264099844 NDMP    0   [Failed]    tuesday

您可能需要查看您的数据,看看是否需要进行其他转换

【讨论】:

  • 假设如果我想删除所有clientHostname以xyz开头的行,那也可以吗?
  • 你可以做一个字典理解来过滤掉clientHostname == "xyz.com"的条目
  • 我试过了,但没有成功,请你帮忙写代码。
  • 请发布您的预期输出
  • 我正在尝试 {name:[name == 'xyz.com'] 但它似乎不起作用。
【解决方案2】:

您将能够以df['attributes'][0][3]['key']、df['attributes'][0][3]['values'] 获取策略工作流程名称 和 status 为 df['instances'][**i**][0]['status'],其中 i 是记录号。

试试这个:

import json
import requests
import pandas as pd
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
pd.set_option('display.width', 100)

a = [{'attributes': [{'key': '*policy action jobid', 'values': ['289903']}, {'key': '*policy action name', 'values': ['backup']}, {'key': '*policy name', 'values': ['Daily_Backups']}, {'key': '*policy workflow name', 'values': ['tuesday']}, {'key': 'clone retention policy', 'values': ['   504:   5:  34']}, {'key': 'group', 'values': ['tuesday']}, {'key': 'saveset features', 'values': ['CLIENT_SAVETIME']}], 'browseTime': '2020-05-19T23:57:41+08:00', 'clientHostname': 'xyz.com', 'clientId': '7d391c52-00000004-5cda459d-5c1', 'creationTime': '2020-04-28T21:29:25+08:00', 'fileCount': 0, 'id': '1eb1', 'instances': [], 'level': 'Full', 'links': [{'href': 'https://iservera/backups/1ec1', 'rel': 'item'}], 'name': '/abc', 'retentionTime': '2020-05-19T23:57:41+08:00', 'saveTime': '2020-04-28T21:27:07+08:00', 'shortId': '2177', 'size': {'unit': 'Byte', 'value': 0}, 'type': 'File'}, {'attributes': [{'key': '*policy action jobid', 'values': ['2803']}, {'key': '*policy action name', 'values': ['backup: 1589']}, {'key': '*policy name', 'values': ['Daily_Backups: 159']}, {'key': '*policy workflow name', 'values': ['tuesday: 1588079529']}, {'key': '*ss clone retention', 'values': ['          1588079529:          1588079590:   1824409']}, {'key': 'group', 'values': ['tuesday']}, {'key': 'saveset features', 'values': ['CLIENT_SAVETIME']}], 'browseTime': '2020-05-19T23:57:42+08:00', 'clientHostname': 'abc.com', 'clientId': 'ec3dc1', 'completionTime': '2020-04-28T21:29:47+08:00', 'creationTime': '2020-04-28T21:13:10+08:00', 'fileCount': 0, 'id': 'cc1', 'instances': [{'clone': False, 'id': '1588079529', 'status': 'Aborted', 'volumeIds': ['245614341']}], 'level': 'Full', 'links': [{'href': 'https://abc/backups/c771', 'rel': 'item'}], 'name': '/xyz', 'retentionTime': '2020-05-19T23:57:42+08:00', 'saveTime': '2020-04-28T21:10:53+08:00', 'shortId': '2141727718', 'size': {'unit': 'Byte', 'value': 36264099844}, 'type': 'NDMP'}]
df = pd.json_normalize(a)
status = []
policy = []
for attribute in df['attributes']:
    policy.append(attribute[3]['values'])

for instance in df['instances']:
    if len(instance) == 0:
        status.append('-')
    else:
        for i in instance:
            status.append(i['status'])
a = df[['clientHostname','completionTime','size.value','type','fileCount']]
a.insert(5, 'policy', policy)
a.insert(6, 'status', status)

pandas.io.json.json_normalize 也已弃用,请改用 pandas.json_normalize

【讨论】:

  • 你能在代码中帮忙吗,我猜这样它只会打印一次它的实例。
  • 实际上,您正在尝试从嵌套的 JSON 创建一个数据框(如果您尝试在 jupyter notebook 中打印整个 df,您可以看到更好 - attrbute 字段包含整个列表)。因此,要获得所需的输出,您可以创建另一个结果数据框,该数据框将通过迭代当前数据框来填充。如果你愿意,我可以帮你写代码。
【解决方案3】:

假设属性和实例字典的格式在整个数据帧中保持不变:

a = raw_json
df_temp = json_normalize(a)

创建状态和策略工作流名称列表

statuses = [i[0]['status']if len(i)>0 else np.nan for i in df_temp['instances']]
policy_workflow_names = [i[3]['values'] if len(i)>0 else np.nan for i in df_temp['attributes']]

属性和实例列中值的格式必须保持不变,否则这将不起作用。

获得这两个列表后,将它们放入最终数据框中。

a = df[['clientHostname','completionTime','size.value','type','fileCount']]
a['policy workflow name'] = policy_workflow_names
a['statuses'] = statuses

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-19
    相关资源
    最近更新 更多