Как добавить JSON в a .файл json?

#python #json

Вопрос:

Я пытаюсь записать результаты в JSON формате в .json файл. Файл содержит МАССИВ JSON.

Проблема в том, что таких результатов десятки тысяч, и делать это таким образом довольно неэффективно:

  1. json.load файл
  2. добавьте результат
  3. json.dump файл

Есть ли способ добавить результаты в конец файла без необходимости загружать файл?

Это мой (неэффективный) метод:

 def append_to_file(dct: dict, filepath: str) -> None:
    if os.path.exists(filepath):
        with open(filepath) as f:
            try:
                content = json.load(f)
            except json.JSONDecodeError:
                content = []
    else:
        content = []
    content.append(dct)
    with open(filepath, 'w') as f:
        json.dump(content, f, indent=4)
 

РЕДАКТИРОВАТЬ — это моя попытка:

 class JsonWriter:
    def __init__(self, filepath):
        self.filepath = filepath
        with open(filepath, 'w') as f:
            f.write('[')

    def write_dict(self, dct: dict) -> None:
        jsn = json.dumps(dct)
        with open(self.filepath, 'a') as f:
            f.write(',n')
            f.write(jsn)

    def close(self):
        with open(self.filepath, 'a') as f:
            f.write('n')
            f.write(']')
 

Что почти работает, но добавляет», » после левой скобки.

 jw = JsonWriter('/home/...')
jw.write_dict({1:1})
jw.write_dict({1:1})
jw.write_dict({1:1})
jw.write_dict({1:1})
jw.close()
 

Результат:

 [,
{"1": 1},
{"1": 1},
{"1": 1},
{"1": 1}
]
 

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

1. Откройте файл в виде текстового файла для чтения и записи, найдите до конца, а затем прочитайте символы с конца , чтобы найти, где заканчивается массив (т. Е. Непосредственно перед внешним ] , начните записывать новые элементы, а затем перепишите конец массива.

2. Знаете ли вы, как добавлять в файл, независимо от JSON?

3. добавление @mkrieger1 не принесет много пользы, вам нужно избавиться от старого конца предыдущего массива.

4. @Grismar это звучит как определенный способ сломать структуру файла

5. Я работал над такой функцией, но есть проблема, что в МАССИВЕ JSON не может быть запятой после последнего элемента.

Ответ №1:

Взгляните на строки json, это формат, который соответствует тому, что вам нужно
https://jsonlines.org/examples/

В файле jsonl каждая строка сама по себе является допустимым json, таким образом, вы можете просто

 # to read
data = []
with open('my_file.jsonl') as f:
    for line in f:
        data.append(json.loads(line))

# to write a new line
with open('my_file.jsonl', 'a') as f:
    f.write(json.dumps(some_data)   'n')
 

Таким образом, вы можете добавлять элементы в «массив», не читая его сначала

Ответ №2:

Если у вас нет контроля над файлом json, с которого вы начинаете, но вы знаете, что это допустимый json и он содержит только массив (с любым содержимым), это работает:

 import os
import json


some_data = [
    1, 2, 3, 4, 
    "one", "two", "three", 
    [1, 2, 3], 
    {1: "one", 2: "two"}, {3: "one", 4: "two"}
]


def append_to_json_arr(fn, data):
    end = ''
    was_empty = True
    with open(fn, 'r ') as f:
        f.seek(0, os.SEEK_END)
        i = f.tell()
        while i >= 0:
            f.seek(i)
            end  = (ch := f.read(1))
            if ch == ']':
                j = i - 1
                while j >= 0:
                    f.seek(j)
                    ch = f.read(i)
                    if ch == '[':
                        f.seek(i)
                        break
                    elif ch.strip():
                        f.seek(i)
                        was_empty = False
                        break
                break
            i -= 1
        json_text = ','.join(json.dumps(item) for item in data)
        if not was_empty:
            json_text = ','   json_text
        f.write(json_text)
        f.write(end)


# starting with an empty one for example
with open('test.json', 'w') as f:
    json.dump([], f)

# adding all the data at once
append_to_json_arr('test.json', some_data)

# adding the data again in lists of one item at a time
for item in some_data:
    append_to_json_arr('test.json', [item])
 

Что append_to_json_arr :

  • найдите конец файла
  • считывайте из него символы, пока не найдете конец массива (поскольку он является допустимым json и содержит массив, вы должны найти ]
  • затем первый символ без пробелов перед ним [ -это символ для пустого списка или что-либо еще, если список содержит что-то
  • запишите новые элементы в конце списка, затем перепишите конец.

Для более надежной функции вы можете иметь дело с искаженными файлами или, возможно, с файлами, в которых есть json, но нет списка.

Ответ №3:

Вы можете json-сериализовать свои словари отдельно, в строки, и хранить их в массиве строк. Тогда легко обрабатывать только массивную часть json в обычном python, вам просто нужно написать открытые и закрытые скобки и соединить представление json ваших словарей с «, «:

 # This will be an array of strings
data = []

while True:
    # Do whatever processing you need to do to produce dcf

    # Serialize just the dcf dictionary
    data.append(json.dumps(dcf))
    
with open('toto.json', 'w') as f:
    f.write(f'[ {", ".join(data)} ]')