Как дополнить json файл

У меня имеется вот такой код:

import json

for i in range(3):
    b = [{'name': i,'year': i+1}]
    print(b)
    with open('json.json', 'w+', encoding='utf-8') as file:
        json.dump(b,file,indent=4, ensure_ascii=False)

Мне нужно чтобы на выходе я получил

[
    {
        "name": 0,
        "year": 1
    },
    {
        "name": 1,
        "year": 2
    },
    {
        "name": 2,
        "year": 3
    }
]

Но я получаю это

[
    {
        "name": 2,
        "year": 3
    }
]

Как мне нужно изменить код, что бы я получил нужный мне результат?


Ответы (2 шт):

Автор решения: Рустам Рысаев

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

Вот исправленный код:

import json

result = []

for i in range(3):
    result.append({'name': i, 'year': i + 1})

with open('json.json', 'w+', encoding='utf-8') as file:
    json.dump(result, file, indent=4, ensure_ascii=False)
→ Ссылка
Автор решения: mrgervant

Если нужно именно дополнять файл, а не предварительно накопить все данные, то можно:

  • извлекать текущие данные из файла
  • добавлять элемент в список
  • перезаписывать файл новым списком
  • повторять процесс для следующего элемента

Это будет актуально, если требуется дополнять список в разных частях программы, а не в рамках одного цикла - где предварительный сбор выгоднее и проще. Можно использовать класс для хранилища, чтобы его экземпляр передавать в требуемые функции/классы.

Пример для хранения и накопления данных в списке внутри json-а:

import json

class ListStorage:
    def __init__(self, file_path):
        self.file_path = file_path

    def add_item(self, item):
        data = self.read_file()
        data.extend(self._convert_to_list(item))
        self.write_file(data)

    def read_file(self):
        with open(self.file_path, 'r', encoding='utf-8') as f:
            try:
                data = json.load(f)
            except json.decoder.JSONDecodeError:
                data = []
        return self._convert_to_list(data)

    def write_file(self, data):
        with open(self.file_path, 'w', encoding='utf-8') as f:
            json.dump(self._convert_to_list(data), f, indent=4, ensure_ascii=False)

    @staticmethod
    def _convert_to_list(data):
        if not isinstance(data, list):
            data = [data]
        return data

Использование:

storage = ListStorage('json.json')

a = {'name': 'a', 'year': 1}
storage.add_item(a)

b = [{'name': 'b', 'year': 2}]
storage.add_item(b)

cd = [{'name': 'c', 'year': 3}, {'name': 'd', 'year': 4}]
storage.add_item(cd)

Результат:

[
    {
        "name": "a",
        "year": 1
    },
    {
        "name": "b",
        "year": 2
    },
    {
        "name": "c",
        "year": 3
    },
    {
        "name": "d",
        "year": 4
    }
]
→ Ссылка