如何使用 python 从 json 文件中检索数据

how to retrieve data from json file using python

我正在执行 api 请求以获取 json 文件进行解析并转换为数据帧。 Json 文件有时可能有空字段,我发布了 2 种可能的情况,其中第一个 json 填充有我正在寻找的字段,第二个 json 文件有该字段为空。

第一个 json 文件:

print(resp2)

{
  "entityId": "proc_1234",
  "displayName": "oracle12",
  "firstSeenTms": 1639034760000,
  "lastSeenTms": 1650386100000,
  "properties": {
    "detectedName": "oracle.sysman.gcagent.tmmain.TMMain",
    "bitness": "64",
    "jvmVendor": "IBM",
    "metadata": [
      {
        "key": "COMMAND_LINE_ARGS",
        "value": "/usr/local/oracle/oem/agent12c/agent_13.3.0.0.0"
      },
      {
        "key": "EXE_NAME",
        "value": "java"
      },
      {
        "key": "EXE_PATH",
        "value": "/usr/local/oracle/oem/agent*c/agent_*/oracle_common/jdk/bin/java"
      },
      {
        "key": "JAVA_MAIN_CLASS",
        "value": "oracle.sysman.gcagent.tmmain.TMMain"
      },
      {
        "key": "EXE_PATH",
        "value": "/usr/local/oracle/oem/agent12c/agent_13.3.0.0.0/oracle_common/jdk/bin/java"
      }
    ]
   }
}

第 2 个 Json 文件:

print(resp2)

{
  "entityId": "PROCESS_GROUP_INSTANCE-FB8C65551916D57D",
  "displayName": "Windows System",
  "firstSeenTms": 1619147697131,
  "lastSeenTms": 1653404640000,
  "properties": {
    "detectedName": "Windows System",
    "bitness": "32",
    "metadata": [],
    "awsNameTag": "Windows System",
    "softwareTechnologies": [
      {
        "type": "WINDOWS_SYSTEM"
      }
    ],
    "processType": "WINDOWS_SYSTEM"
 
  }
}

如您所见元数据": [] 空。

我需要提取 entityId、detectedName,如果 metada 有数据,我需要获取 EXE_NAME 和 EXE_PATH。如果 metada 部分为空,我仍然需要从这个 json 文件中获取 entityId 和 detectedName 并形成一个数据框。

所以,我这样做了:

        #retrieve the detecteName value from the json
        det_name = list(resp2.get('properties','detectedName').values())[0]
        #retrieve EXE_NAME, EXE_PATH and entityId from the json. This part works when metata section has data
        Procdf=(pd.json_normalize(resp2, record_path=['properties', 'metadata'], meta=['entityId']).drop_duplicates(subset=['key']).query("key in ['EXE_NAME','EXE_PATH']").assign(detectedName=det_name).pivot('entityId', 'key', 'value').reset_index())
       #Add detectedName to the Procdf data frame
        Procdf["detectedName"] = det_name

上面的代码片段在元数据有数据时有效,如果它没有数据[],我仍然需要创建一个数据框,其中entityId、detectedName和EXE_NAME和EXE_PATH为空。

我该怎么做?现在当 metadat[] 时,我得到这个错误名称 'key' is not defined 并跳过 json.

只需检查元数据是否为空 if resp2.get("metadata") == []。如果是,则只需执行以下操作:

Procdf = pd.DataFrame(columns=["entityId", "detectedName", "EXE_NAME", "EXE_PATH"]).

如果不是,则使用您的代码。

为什么不根据 metadata 是否有价值来创建一个新的字典?

这是一个示例(这应该适用于两种响应类型):

import pandas as pd


def find_value(response: dict, key: str) -> str:
    result = []
    try:
        for x in response['properties']['metadata']:
            if x['key'] == key:
                result.append(x['value'])
    except KeyError:
        return ""
    return result[0] if result else ""


def get_values(response: dict) -> dict:
    return {
              "entityId": response['entityId'],
              "displayName": response['displayName'],
              "EXE_NAME": find_value(response, 'EXE_NAME'),
              "EXE_PATH": find_value(response, 'EXE_PATH'),
            }


sample_response = {
    "entityId": "PROCESS_GROUP_INSTANCE-FB8C65551916D57D",
    "displayName": "Windows System",
    "firstSeenTms": 1619147697131,
    "lastSeenTms": 1653404640000,
    "properties": {
        "detectedName": "Windows System",
        "bitness": "32",
        "awsNameTag": "Windows System",
        "metadata": [],
        "softwareTechnologies": [
            {
                "type": "WINDOWS_SYSTEM"
            }
        ],
        "processType": "WINDOWS_SYSTEM"

    }
}

print(pd.json_normalize(get_values(sample_response)))

metadata 为空的示例输出:

                                  entityId     displayName EXE_NAME EXE_PATH
0  PROCESS_GROUP_INSTANCE-FB8C65551916D57D  Windows System            

还有一个 metadata 携带数据:

    entityId  ...                                           EXE_PATH
0  proc_1234  ...  /usr/local/oracle/oem/agent*c/agent_*/oracle_c...