如何使用python处理复杂的嵌套JSON数据?
How to deal with complex nested JSON data using python?
我有这样一条消息。
该消息是在执行 .ParseFromString() 之后派生的。这些消息正在通过 ZMQ 以 protobuf 格式传输。
summaries {
key: "node_A"
value {
value_A {
data_1: 29994
data_2: 0.07402841001749039
data_3: -6.621330976486206e-05
}
some_activity {
sys_activity {
key: "arch_prctl"
value: 174
}
sys_activty {
key: "execve"
value: 174
}
sys_activity {
key: "fork"
value: 261
}
some_events_A: 174
some_events_B: 261
}
new_activity {
sys_new_activity {
key: "close"
value: 232
}
sys_new_activity {
key: "open"
value: 116
}
some_new_events: 116
}
more_activity {
}
error_activity {
}
some_alerts {
}
}
}
我需要return输出为
some_activity: ["arch_prctl","execve","fork"],
some_events_A: 174
some_events_B: 261
我可以通过使用 value_A.data_1
来获得 value_A 字段
但我发现很难 return 剩余的嵌套字段。我尝试使用 json.dumps 但它给了我 JSON object is not a serializable 错误。
some_activity 中 sys_activty 的数量各不相同,并不总是如下所示的 3 个值。
如果问题不清楚,请告诉我。假设发送此消息的服务不可编辑,我们只能选择在客户端读取和提供所需的输出。提前致谢
你可以试试这个,请不要因为这个丑陋的解决方案而打我
import regex as re
import json
jstring = ""
f = open("brokenjson.txt", "r")
for x in f:
a = x.strip()
if a[-1] != "{":
a += ","
else:
a = a.replace("{", ": {") # add `:` to key : value pair
if ":" in a:
b = a.split(":")
if "\"" not in b[0]:
a = "\"" + b[0].strip() + "\": " + b[1] # key don't have double quotes "
jstring += a
jstring = jstring.replace(",}", "}") # remove trailing commas
if jstring[-1] == ",":
jstring = jstring[:-1] # check if trailing commas at the end or not
if jstring[0] != "{" and jstring[0] != "[":
jstring = "{" + jstring + "}" # add bracket
result = json.loads(jstring)
distActivity = {}
distEvent = {}
for key, val in result["summaries"]["value"].items():
if "activity" in key:
if key not in distActivity:
distActivity[key] = []
for k,v in val.items():
if "activity" in k:
distActivity[key].append(v["key"])
if "event" in k:
distEvent[k] = v
print(distActivity)
print(distEvent)
因为你的样本有一些重复的键,所以我只得到了这个结果
{'some_activity': ['fork'], 'new_activity': ['open'], 'more_activity': [], 'error_activity': []}
{'some_events_A': 174, 'some_events_B': 261, 'some_new_events': 116}
使用 MessageToJson() 转换 protobuf 而不是 ParseFromString() 解决了问题
我有这样一条消息。 该消息是在执行 .ParseFromString() 之后派生的。这些消息正在通过 ZMQ 以 protobuf 格式传输。
summaries {
key: "node_A"
value {
value_A {
data_1: 29994
data_2: 0.07402841001749039
data_3: -6.621330976486206e-05
}
some_activity {
sys_activity {
key: "arch_prctl"
value: 174
}
sys_activty {
key: "execve"
value: 174
}
sys_activity {
key: "fork"
value: 261
}
some_events_A: 174
some_events_B: 261
}
new_activity {
sys_new_activity {
key: "close"
value: 232
}
sys_new_activity {
key: "open"
value: 116
}
some_new_events: 116
}
more_activity {
}
error_activity {
}
some_alerts {
}
}
}
我需要return输出为
some_activity: ["arch_prctl","execve","fork"],
some_events_A: 174
some_events_B: 261
我可以通过使用 value_A.data_1
来获得 value_A 字段但我发现很难 return 剩余的嵌套字段。我尝试使用 json.dumps 但它给了我 JSON object is not a serializable 错误。
some_activity 中 sys_activty 的数量各不相同,并不总是如下所示的 3 个值。
如果问题不清楚,请告诉我。假设发送此消息的服务不可编辑,我们只能选择在客户端读取和提供所需的输出。提前致谢
你可以试试这个,请不要因为这个丑陋的解决方案而打我
import regex as re
import json
jstring = ""
f = open("brokenjson.txt", "r")
for x in f:
a = x.strip()
if a[-1] != "{":
a += ","
else:
a = a.replace("{", ": {") # add `:` to key : value pair
if ":" in a:
b = a.split(":")
if "\"" not in b[0]:
a = "\"" + b[0].strip() + "\": " + b[1] # key don't have double quotes "
jstring += a
jstring = jstring.replace(",}", "}") # remove trailing commas
if jstring[-1] == ",":
jstring = jstring[:-1] # check if trailing commas at the end or not
if jstring[0] != "{" and jstring[0] != "[":
jstring = "{" + jstring + "}" # add bracket
result = json.loads(jstring)
distActivity = {}
distEvent = {}
for key, val in result["summaries"]["value"].items():
if "activity" in key:
if key not in distActivity:
distActivity[key] = []
for k,v in val.items():
if "activity" in k:
distActivity[key].append(v["key"])
if "event" in k:
distEvent[k] = v
print(distActivity)
print(distEvent)
因为你的样本有一些重复的键,所以我只得到了这个结果
{'some_activity': ['fork'], 'new_activity': ['open'], 'more_activity': [], 'error_activity': []}
{'some_events_A': 174, 'some_events_B': 261, 'some_new_events': 116}
使用 MessageToJson() 转换 protobuf 而不是 ParseFromString() 解决了问题