Редактирование файла Json в Python

#python #json #python-3.x #python-2.7 #yaml

Вопрос:

Я хочу заменить значения в файле manifest.json. Мой файл manifest.json выглядит так

 {
  "uat1": {
    "database": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
     },
    "services1": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      },
    "p_database": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
     },
    "p_services": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      },
    "Build_d": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      }
     },
  "uat2": {
    "database": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
     },
    "services1": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      },
    "p_database": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
     },
    "p_services": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      },
    "Build_d": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      }
     }
 

Всякий раз, когда будет какое-либо обновление базы данных uat1 (или любого другого компонента), он обновит файл манифеста с указанием версии и sysdate. Мой выходной манифест.json будет выглядеть так

 {
  "uat1": {
    "database": {
      "artifact_version": "12.0.3",
      "date": "04/08/2021 19:50:14"
     },
    "services1": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      },
    "p_database": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
     },
    "p_services": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      },
    "Build_d": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      }
     },
  "uat2": {
    "database": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
     },
    "services1": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      },
    "p_database": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
     },
    "p_services": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      },
    "Build_d": {
      "artifact_version": "0.0.1",
      "date": "sysdate"
      }
     }
 

Я пишу код на python, но значения не отображаются должным образом:
Я запускаю python, как test.py 12.0.3 база данных uat1
Мой код выглядит так:

 import sys
import json
from datetime import datetime

version = str(sys.argv[1])

env = str(sys.argv[2])
script = str(sys.argv[3])
now = datetime.now()
sdate = now.strftime("%d/%m/%Y %H:%M:%S")
print(sdate)

print("%s %s %s" % (version, env, script))

with open("C:/Users/lohapri/PycharmProjects/RFOS/manifest.json", "r") as f1:
    data = json.load(f1)
f1.close()
#print(data)

for k1, v1 in data.items():
    if k1 == env:
        for k2, v2 in v1.items():
            if k2 == script:
                v2['artifact_version'] = version
                v2['date'] = sdate
            print(v2)
            with open("C:/Users/lohapri/PycharmProjects/RFOS/manifest.json", "w") as f2:
               for i in k1:
                 json.dump(v2, f2, indent=4)
              

 

Вывод в manifest.json, который я получаю, это:

 {
    "artifact_version": "0.0.1",
    "date": "sysdate"
}{
    "artifact_version": "0.0.1",
    "date": "sysdate"
}{
    "artifact_version": "0.0.1",
    "date": "sysdate"
}{
    "artifact_version": "0.0.1",
    "date": "sysdate"
}
 

Пожалуйста, скажите мне, как мне следует действовать.

Ответ №1:

У вас есть dict, и нет необходимости повторять его, и вам нужно сбросить json только один раз

 data[env][script].update(
    artifact_version = version,
    date = sdate
)

with open("C:/Users/lohapri/PycharmProjects/RFOS/manifest.json", "w") as f2:
    json.dump(data, f2, indent=4)
 

Ответ №2:

Просто проанализируйте его, обновите необходимое значение и запишите его обратно в файл.

 with open("manifest.json") as f:
    d = json.load(f)

d[env][script] = {"artifact_version": ..., "date": ...}

with tempfile.NamedTemporaryFile(delete=False) as f:
    try:
        json.dump(d, f)
    except Exception:
        raise
    else:
        os.rename(f.name, "manifest.json")
 

Если вас не беспокоит manifest.json усечение перед успешной записью новых данных, вы можете сократить третий шаг до

 with open("manifest.json", "w") as f:
    json.dump(d, f)
        
 

Ответ №3:

Нет, чтобы «отредактировать» json файл, вам нужно загрузить весь файл с помощью: data = json.load(f1) , затем выполнить преобразование, а затем снова записать всю запись:

 with open("C:/Users/lohapri/PycharmProjects/RFOS/manifest.json", "r") as f1:
    data = json.load(f1)
#no close needed
#print(data)

for k1, v1 in data.items():
    if k1 == env:
        for k2, v2 in v1.items():
            if k2 == script:
                v2['artifact_version'] = version
                v2['date'] = sdate
            print(v2)

with open("C:/Users/lohapri/PycharmProjects/RFOS/manifest.json", "w") as f2:
  json.dump(data, f2, indent=4)