大型 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-destinationrt-entryas-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"
      ]
   }
]