Непрерывная запись файла JSON, содержащего массив

#python #json

#python #json

Вопрос:

Я хочу создать файл JSON с помощью Python. Структура JSON выглядит следующим образом :

 {
    "index_pattern" : "all_packets"
    "packets" : [
        {
            "packet_type" : "TCP"
            "source_ip" : "192.168.0.2",
            "destination_ip" : "192.168.0.114"
        },
        {
            "packet_type" : "ICMP"
            "source_ip" : "192.168.0.2",
            "destination_ip" : "192.168.0.114"
        }
    ]
}
  

Всякий раз, когда я перехватываю пакет с помощью модуля wireshark, я хочу добавить этот пакет, скажем, в файл myoutput.json. Проблема в том, что используется что-то вроде

 f = open("myoutput.json", "a")
f.write({
            "packet_type" : "ICMP"
            "source_ip" : "192.168.0.2",
            "destination_ip" : "192.168.0.114"
        })
  

не подходит, потому что у меня нет изящного завершения работы, и я не могу добавить необходимый завершающий параграф для завершения JSON. Итак, мне нужно записать между массивом пакетов. Каков наилучший способ добиться этого.

Комментарии:

1. Не могли бы вы вместо этого сохранить это в базе данных NoSQL и просто отправить пакеты туда?

2. Привет, спасибо за внимание. Моим требованием к проекту является создание файла JSON в качестве выходных данных, которые может прочитать другая программа (скажем, X). И программа X уже использует ElasticSearch, поэтому мы можем не включать в проект другой инструмент хранения. Вот почему я, мы не можем догадаться. @doctorlove

Ответ №1:

При записи файла:

 import json
with open('myoutput.json', 'a') as fo:
    json.dump({
        "packet_type" : "ICMP",
        "source_ip" : "192.168.0.2",
        "destination_ip" : "192.168.0.114"
          }, fo)
  

При чтении файла выполните:

 with open('myoutput.json') as fo:
    data = fo.read()
    data = data.replace('}{', '},{')
    data = '['   data   ']'
    data = json.loads(data)
    result = {"index_pattern" : "all_packets",
              "packets": data}
  

Редактировать

Вы также можете создать вспомогательный класс для этого:

 import json

class WriteObject:
    def __init__(self, fname='myoutput.json'):
        self.fname = fname

    def push(self, data):
        #    data_example={
        #    "packet_type" : "ICMP",
        #    "source_ip" : "192.168.0.2",
        #    "destination_ip" : "192.168.0.114"
        #    }
        with open(self.fname, 'a') as fo:
            json.dump(data, fo)
    def get_all(self):
        with open(self.fname) as fo:
            data = fo.read()
            data = data.replace('}{', '},{')
            data = '['   data   ']'
            data = json.loads(data)
            result = {"index_pattern" : "all_packets",
                      "packets": data}
        return result

# usage
obj = WriteObject()

obj.push({
        "packet_type" : "ICMP",
        "source_ip" : "192.168.0.2",
        "destination_ip" : "192.168.0.114"
          })
  

Комментарии:

1. Но вы действительно проверяли, работает ли ваш код?

2. @taras, Да, в Jupyter!

3. Привет, спасибо за ответ. Чтобы было более понятно, я хочу выполнить операцию push в поле packets, которое находится в файле. Просто чтобы продемонстрировать, что это такое, myoutput.json[«пакеты»].push({ «packet_type»: «ICMP», «source_ip»: «192.168.0.2», «destination_ip»: «192.168.0.114» })

4. Решение с реализацией класса решило это. Спасибо всем вам <3

Ответ №2:

Одним из возможных решений является json.load перенос всего файла, скажем, в объект python data и добавление packet к data["packets"] . Затем вам нужно записать обновленный data обратно в ваш json-файл.
Недостатком этого подхода является необходимость постоянного чтения и записи данных в json-файл.

Это можно улучшить, объединив список пакетов (таким образом, вы временно сохраняете свои пакеты в packets списке) и обновляя файл json только тогда, когда он достигает некоторого предопределенного размера (скажем, когда len(packets) == 20 ). После этого вы можете очистить его packets и снова начать собирать в него данные.