Python读取JSON文件并进行修改

时间:2014-01-10 03:34:57

标签: python json file-io

您好我正在尝试从json文件获取数据并插入和id然后执行POST REST。 我的文件data.json有:

{
    'name':'myname'
}

我想添加一个id,以便json数据看起来像:

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

所以我试过了:

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

我无法加载json格式文件。 我应该怎么做才能将json文件转换为json对象并添加另一个id值。

6 个答案:

答案 0 :(得分:56)

使用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

答案 1 :(得分:29)

falsetru的解决方案很好,但有一个小错误:

假设原始'id'长度大于5个字符。当我们使用新的'id'(134只有3个字符)进行转储时,从文件中的位置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)

答案 2 :(得分:2)

我想介绍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)

答案 3 :(得分:0)

确实有很多方法可以做到这一点,并且以上所有方法都是一种或另一种有效的方法……让我添加一个简单的命题。因此,假设您当前的现有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'

接下来,我们再次使用'with 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请求

答案 4 :(得分:0)

尝试以下脚本:

with open("data.json") as f:
    data = json.load(f)
    data["id"] = 134
    json.dump(data, open("data.json", "w"), indent = 4)

结果是:

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

只是排列有所不同,您可以通过将“数据”类型转换为列表,然后根据需要进行排列,然后返回并保存文件来解决问题,如下所示:

index_add = 0
with open("data.json") as f:
    data = json.load(f)
    data_li = [[k, v] for k, v in data.items()]
    data_li.insert(index_add, ["id", 134])
    data = {data_li[i][0]:data_li[i][1] for i in range(0, len(data_li))}
    json.dump(data, open("data.json", "w"), indent = 4)

结果是:

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

您可以添加if条件以便不重复输入密钥,只需更改它,就像这样:

index_add = 0
n_k = "id"
n_v = 134
with open("data.json") as f:
    data = json.load(f)
    if n_k in data:
        data[n_k] = n_v
    else:
       data_li = [[k, v] for k, v in data.items()]
       data_li.insert(index_add, [n_k, n_v])
       data = {data_li[i][0]:data_li[i][1] for i in range(0, len(data_li))}
    json.dump(data, open("data.json", "w"), indent = 4)

答案 5 :(得分:0)

这个实现应该足够了:

with open(jsonfile, 'r') as file:
    data = json.load(file)
    data[id] = value

with open(jsonfile, 'w') as file:
    json.dump(data, file)

使用上下文管理器打开 jsonfile。 data 保存更新后的对象并以“w”模式转储到覆盖的 jsonfile 中。