Python читает JSON файл и модифицирует

Привет, я пытаюсь взять данные из json файла и вставить и id, а затем выполнить POST REST. у моего файла data.json есть:

{
    'name':'myname'
}

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

 {
     'id': 134,
     'name': 'myname'
 }

Итак, я попробовал:

import json
f = open("data.json","r")
data = f.read()
jsonObj = json.loads(data)

Я не могу загрузить файл формата json. Что я должен сделать, чтобы преобразовать json файл в json-объект и добавить другое значение id.

Ответы

Ответ 1

Задайте элемент с помощью data['id'] = ....

import json

with open('data.json', 'r+') as f:
    data = json.load(f)
    data['id'] = 134 # <--- add `id` value.
    f.seek(0)        # <--- should reset file position to the beginning.
    json.dump(data, f, indent=4)
    f.truncate()     # remove remaining part

Ответ 2

Решение falsetru приятно, но имеет небольшую ошибку:

Предположим, что исходная длина "id" больше 5 символов. Когда мы сбрасываем новый "id" (134 только с тремя символами), длина строки, записанной из позиции 0 в файле, меньше более короткой, чем исходная длина. Дополнительные символы (например, '}') оставлены в файле из исходного содержимого.

Я решил, что заменив исходный файл.

import json
import os

filename = 'data.json'
with open(filename, 'r') as f:
    data = json.load(f)
    data['id'] = 134 # <--- add `id` value.

os.remove(filename)
with open(filename, 'w') as f:
    json.dump(data, f, indent=4)

Ответ 3

Я хотел бы представить модифицированную версию решения Vadim. Это помогает обрабатывать асинхронные запросы на запись/изменение файла JSON. Я знаю, что это не было частью первоначального вопроса, но может быть полезным для других.

В случае асинхронной модификации файла os.remove(filename) вызовет FileNotFoundError если запросы появляются часто. Чтобы преодолеть эту проблему, вы можете создать временный файл с измененным содержимым, а затем переименовать его, заменив старую версию. Это решение прекрасно работает как для синхронных, так и для асинхронных случаев.

import os, json, uuid

filename = 'data.json'
with open(filename, 'r') as f:
    data = json.load(f)
    data['id'] = 134 # <--- add 'id' value.
    # add, remove, modify content

# create randomly named temporary file to avoid 
# interference with other thread/asynchronous request
tempfile = os.path.join(os.path.dirname(filename), str(uuid.uuid4()))
with open(tempfile, 'w') as f:
    json.dump(data, f, indent=4)

# rename temporary file replacing old file
os.rename(tempfile, filename)

Ответ 4

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

{
     "name":"myname"
}

И вы хотите добавить этот новый контент json (добавив ключ "id")

{
     "id": "134",
     "name": "myname"
 }

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

import json 

# first, get the absolute path to json file
PATH_TO_JSON = 'data.json' #  assuming same directory (but you can work your magic here with os.)

# read existing json to memory. you do this to preserve whatever existing data. 
with open(PATH_TO_JSON,'r') as jsonfile:
    json_content = json.load(jsonfile) # this is now in memory! you can use it outside 'open'

Далее мы снова используем синтаксис "с открытым()" с опцией "w". "w" - это режим записи, который позволяет нам редактировать и записывать новую информацию в файл. Вот уловка, которая работает для нас: любой существующий json с тем же целевым именем записи будет удален автоматически.

Итак, что мы можем сделать сейчас, это просто написать в то же имя файла с новыми данными

# add the id key-value pair (rmbr that it already has the "name" key value)
json_content["id"] = "134"

with open(PATH_TO_JSON,'w') as jsonfile:
    json.dump(json_content, jsonfile, indent=4) # you decide the indentation level

И вот, пожалуйста! data.json должен быть хорош для старого доброго POST-запроса