大型 JSON 文件上的 JMESPath filter/MultiSelect
JMESPath filter/MultiSelect on a large JSON file
数据源是 Juniper 路由器路由 json 中的 table 输出(> 3 GB json 文件)。我最终想要的是能够遍历前缀列表并获得前缀作为路径组合。
#!/usr/bin/env python
import json
from jmespath import search
jsonData = """{
"route-information": [
{
"route-table": [
{
"rt": [
{
"rt-destination": [
{
"data": "2001:db8:1::/48"
}
],
"rt-entry": [
{
"as-path": [
{
"data": "64511 65551 I"
}
]
}
]
},
{
"rt-destination": [
{
"data": "2001:db8:2::/48"
}
],
"rt-entry": [
{
"as-path": [
{
"data": "65536 64496 I"
}
]
}
]
}
]
}
]
}
]
}"""
data = json.loads(jsonData)
query='"route-information"[]."route-table"[].rt[].{\"destination\": \"rt-destination\", path: \"rt-entry\"}'
output = search(query, data)
print(output)
以上 query
结果:
[{'destination': [{'data': '2001:db8:1::/48'}], 'path': [{'as-path': [{'data': '64511 65551 I'}]}]}, {'destination': [{'data': '2001:db8:2::/48'}], 'path': [{'as-path': [{'data': '65536 64496 I'}]}]}]
看起来方向正确。但我想要 prefix : as-path 组合,所以我想去掉“data:”和“as- path.data" 部分(在实际的 json 文件中,此级别上有更多对象,我试图在这里摆脱它们)。
query='"route-information"[]."route-table"[].rt[].{\"destination\": \"rt-destination\", path: \"rt-entry\".\"as-path\"}
and/or
query='"route-information"[]."route-table"[].rt[].{\"destination\": \"rt-destination\", path: \"rt-entry\".\"as-path\".data}'
结果:
[{'destination': [{'data': '2001:db8:1::/48'}], 'path': None}, {'destination': [{'data': '2001:db8:2::/48'}], 'path': None}]
知道为什么“None”和or/how要继续吗?
另一个想法是过滤:
query='"route-information"[]."route-table"[].rt[?"rt-destination".data==`2001:db8:2::/48`]'
然后继续往下走以获得 as-path。但是查询结果在 [[]]
where as
query='"route-information"[]."route-table"[].rt[?"rt-destination".data=="2001:db8:2::/48"]'
导致
[[{'rt-destination': [{'data': '2001:db8:1::/48'}], 'rt-entry': [{'as-path': [{'data': '64511 65551 I'}]}]}, {'rt-destination': [{'data': '2001:db8:2::/48'}], 'rt-entry': [{'as-path': [{'data': '65536 64496 I'}]}]}]]
所以根本没有过滤。
如果您的目标是拥有一组如下所示的数据:
[
{
"destination": "2001:db8:1::/48",
"path": "64511 65551 I"
},
{
"destination": "2001:db8:2::/48",
"path": "65536 64496 I"
}
]
可以简单地通过这个查询来实现:
route-information[].route-table[].rt[].{destination: rt-destination[0].data, path: rt-entry[0].as-path[0].data}
但我怀疑,根据您在 rt-destination
、rt-entry
和 as-path
下的列表,此查询实际上可能会让您遗漏一些数据。
这是一个不太可能让您错过数据的方法,但它是在 path
下创建一个列表,因此生成的 JSON 看起来像:
[
{
"destination": [
"2001:db8:1::/48"
],
"path": [
"64511 65551 I"
]
},
{
"destination": [
"2001:db8:2::/48"
],
"path": [
"65536 64496 I"
]
}
]
查询是:
route-information[].route-table[].rt[].{destination: rt-destination[*].data, path: rt-entry[*].as-path[*].data | [] }
此查询使用展平运算符 |
,这在 working with nested data.
下的示例中进行了说明
这是一个演示这个的脚本:
import jmespath
data = {
"route-information": [
{
"route-table": [
{
"rt": [
{
"rt-destination": [
{
"data": "2001:db8:1::/48"
}
],
"rt-entry": [
{
"as-path": [
{
"data": "64511 65551 I"
}
]
}
]
},
{
"rt-destination": [
{
"data": "2001:db8:2::/48"
}
],
"rt-entry": [
{
"as-path": [
{
"data": "65536 64496 I"
}
]
}
]
}
]
}
]
}
]
}
query = [
'"route-information"[]."route-table"[].rt[].{destination: "rt-destination"[0].data, path: "rt-entry"[0]."as-path"[0].data}',
'"route-information"[]."route-table"[].rt[].{destination: "rt-destination"[*].data, path: "rt-entry"[*]."as-path"[*].data | [] }'
]
print(jmespath.search(query[0], data))
print('---------------------------')
print(jmespath.search(query[1], data))
打印(手工美化):
[
{
"destination":"2001:db8:1::/48",
"path":"64511 65551 I"
},
{
"destination":"2001:db8:2::/48",
"path":"65536 64496 I"
}
]
---------------------------
[
{
"destination":[
"2001:db8:1::/48"
],
"path":[
"64511 65551 I"
]
},
{
"destination":[
"2001:db8:2::/48"
],
"path":[
"65536 64496 I"
]
}
]
数据源是 Juniper 路由器路由 json 中的 table 输出(> 3 GB json 文件)。我最终想要的是能够遍历前缀列表并获得前缀作为路径组合。
#!/usr/bin/env python
import json
from jmespath import search
jsonData = """{
"route-information": [
{
"route-table": [
{
"rt": [
{
"rt-destination": [
{
"data": "2001:db8:1::/48"
}
],
"rt-entry": [
{
"as-path": [
{
"data": "64511 65551 I"
}
]
}
]
},
{
"rt-destination": [
{
"data": "2001:db8:2::/48"
}
],
"rt-entry": [
{
"as-path": [
{
"data": "65536 64496 I"
}
]
}
]
}
]
}
]
}
]
}"""
data = json.loads(jsonData)
query='"route-information"[]."route-table"[].rt[].{\"destination\": \"rt-destination\", path: \"rt-entry\"}'
output = search(query, data)
print(output)
以上 query
结果:
[{'destination': [{'data': '2001:db8:1::/48'}], 'path': [{'as-path': [{'data': '64511 65551 I'}]}]}, {'destination': [{'data': '2001:db8:2::/48'}], 'path': [{'as-path': [{'data': '65536 64496 I'}]}]}]
看起来方向正确。但我想要 prefix : as-path 组合,所以我想去掉“data:”和“as- path.data" 部分(在实际的 json 文件中,此级别上有更多对象,我试图在这里摆脱它们)。
query='"route-information"[]."route-table"[].rt[].{\"destination\": \"rt-destination\", path: \"rt-entry\".\"as-path\"}
and/or
query='"route-information"[]."route-table"[].rt[].{\"destination\": \"rt-destination\", path: \"rt-entry\".\"as-path\".data}'
结果:
[{'destination': [{'data': '2001:db8:1::/48'}], 'path': None}, {'destination': [{'data': '2001:db8:2::/48'}], 'path': None}]
知道为什么“None”和or/how要继续吗?
另一个想法是过滤:
query='"route-information"[]."route-table"[].rt[?"rt-destination".data==`2001:db8:2::/48`]'
然后继续往下走以获得 as-path。但是查询结果在 [[]]
where as
query='"route-information"[]."route-table"[].rt[?"rt-destination".data=="2001:db8:2::/48"]'
导致
[[{'rt-destination': [{'data': '2001:db8:1::/48'}], 'rt-entry': [{'as-path': [{'data': '64511 65551 I'}]}]}, {'rt-destination': [{'data': '2001:db8:2::/48'}], 'rt-entry': [{'as-path': [{'data': '65536 64496 I'}]}]}]]
所以根本没有过滤。
如果您的目标是拥有一组如下所示的数据:
[
{
"destination": "2001:db8:1::/48",
"path": "64511 65551 I"
},
{
"destination": "2001:db8:2::/48",
"path": "65536 64496 I"
}
]
可以简单地通过这个查询来实现:
route-information[].route-table[].rt[].{destination: rt-destination[0].data, path: rt-entry[0].as-path[0].data}
但我怀疑,根据您在 rt-destination
、rt-entry
和 as-path
下的列表,此查询实际上可能会让您遗漏一些数据。
这是一个不太可能让您错过数据的方法,但它是在 path
下创建一个列表,因此生成的 JSON 看起来像:
[
{
"destination": [
"2001:db8:1::/48"
],
"path": [
"64511 65551 I"
]
},
{
"destination": [
"2001:db8:2::/48"
],
"path": [
"65536 64496 I"
]
}
]
查询是:
route-information[].route-table[].rt[].{destination: rt-destination[*].data, path: rt-entry[*].as-path[*].data | [] }
此查询使用展平运算符 |
,这在 working with nested data.
这是一个演示这个的脚本:
import jmespath
data = {
"route-information": [
{
"route-table": [
{
"rt": [
{
"rt-destination": [
{
"data": "2001:db8:1::/48"
}
],
"rt-entry": [
{
"as-path": [
{
"data": "64511 65551 I"
}
]
}
]
},
{
"rt-destination": [
{
"data": "2001:db8:2::/48"
}
],
"rt-entry": [
{
"as-path": [
{
"data": "65536 64496 I"
}
]
}
]
}
]
}
]
}
]
}
query = [
'"route-information"[]."route-table"[].rt[].{destination: "rt-destination"[0].data, path: "rt-entry"[0]."as-path"[0].data}',
'"route-information"[]."route-table"[].rt[].{destination: "rt-destination"[*].data, path: "rt-entry"[*]."as-path"[*].data | [] }'
]
print(jmespath.search(query[0], data))
print('---------------------------')
print(jmespath.search(query[1], data))
打印(手工美化):
[
{
"destination":"2001:db8:1::/48",
"path":"64511 65551 I"
},
{
"destination":"2001:db8:2::/48",
"path":"65536 64496 I"
}
]
---------------------------
[
{
"destination":[
"2001:db8:1::/48"
],
"path":[
"64511 65551 I"
]
},
{
"destination":[
"2001:db8:2::/48"
],
"path":[
"65536 64496 I"
]
}
]