#python #jmespath
#python #jmespath
Вопрос:
Источник данных — это таблица маршрутизации маршрутизатора Juniper, выводимая в формате json (> 3 ГБ 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"}
и / или
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. Но результат запроса в [[]]
where как
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'}]}]}]]
так что никакой фильтрации вообще.
Комментарии:
1. Пример JSON, который вы хотите получить, был бы здесь лучше, чем ваше длинное и довольно неясное описание: поэтому я хотел бы избавиться от части «data:» и «as-path.data»
Ответ №1:
Если ваша цель — иметь набор данных, выглядящий следующим образом:
[
{
"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
, что этот запрос может фактически заставить вас пропустить некоторые данные.
Вот тот, который с меньшей вероятностью заставит вас пропустить данные, но который создает список under 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 | [] }
В этом запросе используется оператор flatten |
, который объясняется в примерах в разделе работа с вложенными данными.
Вот сценарий, демонстрирующий это:
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"
]
}
]