Источник данных — это таблица маршрутизации Juniper Router, выводимая в формате json (json-файл > 3 ГБ). Что я, наконец, хотел бы иметь, так это возможность перебрать список префиксов и получить комбинацию префикса как пути.
#!/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'}]}]}]
Похоже на правильном пути. Но я хотел бы иметь префикс: комбинация as-path, поэтому я хотел бы избавиться от части «data:» и «as-path.data» (в самом файле json на этом уровне гораздо больше объектов и Я пытаюсь избавиться от них здесь).
query='"route-information"[]."route-table"[].rt[].{\"destination\": \"rt-destination\", path: \"rt-entry\".\"as-path\"}
и/или
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}]
Любые идеи, почему «Нет» и/или как действовать?
Другой идеей была фильтрация:
query='"route-information"[]."route-table"[].rt[?"rt-destination".data==`2001:db8:2::/48`]'
а затем продвигаюсь дальше, чтобы получить as-path. Но запрос приводит к [[]]
, где как
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 | [] }
В этом запросе используется оператор сглаживания |
, который объясняется в примерах в разделе работы с вложенными данными.
Вот скрипт, демонстрирующий это:
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"
]
}
]
Пример JSON, который вы стремитесь получить, будет лучше, чем ваше длинное и довольно нечеткое описание: поэтому я хотел бы избавиться от части «data:» и «as-path.data».