#python #json
Вопрос:
Я пытаюсь записать результаты в JSON
формате в .json
файл. Файл содержит МАССИВ JSON.
Проблема в том, что таких результатов десятки тысяч, и делать это таким образом довольно неэффективно:
json.load
файл- добавьте результат
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)} ]')