使用Python将数据附加到json文件

时间:2021-12-25 21:15:31

I'm trying to create a function that would add entries to a json file. Eventually, I want a file that looks like

我正在尝试创建一个将条目添加到json文件的函数。最终,我想要一个看起来像的文件

[{"name" = "name1", "url" = "url1"}, {"name" = "name2", "url" = "url2"}]

etc. This is what I have:

这就是我所拥有的:

def add(args):
    with open(DATA_FILENAME, mode='r', encoding='utf-8') as feedsjson:
        feeds = json.load(feedsjson)
    with open(DATA_FILENAME, mode='w', encoding='utf-8') as feedsjson:
        entry = {}
        entry['name'] = args.name
        entry['url'] = args.url
        json.dump(entry, feedsjson)

This does create an entry such as {"name"="some name", "url"="some url"}. But, if I use this add function again, with different name and url, the first one gets overwritten. What do I need to do to get a second (third...) entry appended to the first one?

这会创建一个条目,例如{“name”=“some name”,“url”=“some url”}。但是,如果我再次使用此添加功能,使用不同的名称和URL,则第一个会被覆盖。我需要做什么才能将第二个(第三个......)条目附加到第一个?

EDIT: The first answers and comments to this question have pointed out the obvious fact that I am not using feeds in the write block. I don't see how to do that, though. For example, the following apparently will not do:

编辑:这个问题的第一个答案和评论指出了一个显而易见的事实,即我没有在写块中使用feed。不过,我不知道该怎么做。例如,以下显然不会这样做:

    with open(DATA_FILENAME, mode='a+', encoding='utf-8') as feedsjson:
    feeds = json.load(feedsjson)
    entry = {}
    entry['name'] = args.name
    entry['url'] = args.url
    json.dump(entry, feeds)

6 个解决方案

#1


26  

You probably want to use a JSON list instead of a dictionary as the toplevel element.

您可能希望使用JSON列表而不是字典作为顶层元素。

So, initialize the file with an empty list:

因此,使用空列表初始化文件:

with open(DATA_FILENAME, mode='w', encoding='utf-8') as f:
    json.dump([], f)

Then, you can append new entries to this list:

然后,您可以将新条目附加到此列表:

with open(DATA_FILENAME, mode='w', encoding='utf-8') as feedsjson:
    entry = {'name': args.name, 'url': args.url}
    feeds.append(entry)
    json.dump(feeds, feedsjson)

Note that this will be slow to execute because you will rewrite the full contents of the file every time you call add. If you are calling it in a loop, consider adding all the feeds to a list in advance, then writing the list out in one go.

请注意,执行速度很慢,因为每次调用add时都会重写文件的全部内容。如果您在循环中调用它,请考虑提前将所有提要添加到列表中,然后一次性写出列表。

#2


25  

json might not be the best choice for on-disk formats; The trouble it has with appending data is a good example of why this might be. Specifically, json objects have a syntax that means the whole object must be read and parsed in order to understand any part of it.

json可能不是磁盘格式的最佳选择;添加数据时遇到的麻烦就是一个很好的例子。具体来说,json对象的语法意味着必须读取和解析整个对象才能理解它的任何部分。

Fortunately, there are lots of other options. A particularly simple one is CSV; which is supported well by python's standard library. The biggest downside is that it only works well for text; it requires additional action on the part of the programmer to convert the values to numbers or other formats, if needed.

幸运的是,还有很多其他选择。一个特别简单的是CSV; python的标准库支持它。最大的缺点是它只适用于文本;如果需要,它需要程序员的额外操作将值转换为数字或其他格式。

Another option which does not have this limitation is to use a sqlite database, which also has built-in support in python. This would probably be a bigger departure from the code you already have, but it more naturally supports the 'modify a little bit' model you are apparently trying to build.

另一个没有这个限制的选项是使用一个sqlite数据库,它在python中也有内置的支持。这可能与您已有的代码有较大不同,但它更自然地支持您显然正在尝试构建的“修改一点”模型。

#3


7  

Append entry to the file contents if file exists, otherwise append the entry to an empty list and write in in the file:

如果文件存在,则将条目附加到文件内容,否则将条目附加到空列表并写入文件:

a = []
if not os.path.isfile(fname):
    a.append(entry)
    with open(fname, mode='w') as f:
        f.write(json.dumps(entry, indent=2))
else:
    with open(fname) as feedsjson:
        feeds = json.load(feedsjson)

    feeds.append(entry)
    with open(fname, mode='w') as f:
        f.write(json.dumps(feeds, indent=2))

#4


4  

Using a instead of w should let you update the file instead of creating a new one/overwriting everything in the existing file.

使用a代替w应该允许您更新文件而不是创建新文件/覆盖现有文件中的所有内容。

See this answer for a difference in the modes.

有关模式的不同,请参阅此答案。

#5


2  

One possible solution is do the concatenation manually, here is some useful code:

一种可能的解决方案是手动连接,这里有一些有用的代码:

import json
def append_to_json(_dict,path): 
    with open(path, 'ab+') as f:
    f.seek(0,2)                                #Go to the end of file    
    if f.tell() == 0 :                         #Check if file is empty
        f.write(json.dumps([_dict]).encode())  #If empty, write an array
    else :
        f.seek(-1,2)           
        f.truncate()                           #Remove the last character, open the array
        f.write(' , '.encode())                #Write the separator
        f.write(json.dumps(_dict).encode())    #Dump the dictionary
        f.write(']'.encode())                  #Close the array

You should be careful when editing the file outside the script not add any spacing at the end.

在脚本外部编辑文件时应该小心,不要在末尾添加任何间距。

#6


1  

You aren't ever writing anything to do with the data you read in. Do you want to be adding the data structure in feeds to the new one you're creating?

您不会写任何与您所读数据有关的内容。您是否希望将Feed中的数据结构添加到您正在创建的新数据中?

Or perhaps you want to open the file in append mode open(filename, 'a') and then add your string, by writing the string produced by json.dumps instead of using json.dump - but nneonneo points out that this would be invalid json.

或者你可能想要以附加模式open(filename,'a')打开文件然后添加你的字符串,通过写json.dumps而不是使用json.dump生成的字符串 - 但是nneonneo指出这将是无效的JSON。

#1


26  

You probably want to use a JSON list instead of a dictionary as the toplevel element.

您可能希望使用JSON列表而不是字典作为顶层元素。

So, initialize the file with an empty list:

因此,使用空列表初始化文件:

with open(DATA_FILENAME, mode='w', encoding='utf-8') as f:
    json.dump([], f)

Then, you can append new entries to this list:

然后,您可以将新条目附加到此列表:

with open(DATA_FILENAME, mode='w', encoding='utf-8') as feedsjson:
    entry = {'name': args.name, 'url': args.url}
    feeds.append(entry)
    json.dump(feeds, feedsjson)

Note that this will be slow to execute because you will rewrite the full contents of the file every time you call add. If you are calling it in a loop, consider adding all the feeds to a list in advance, then writing the list out in one go.

请注意,执行速度很慢,因为每次调用add时都会重写文件的全部内容。如果您在循环中调用它,请考虑提前将所有提要添加到列表中,然后一次性写出列表。

#2


25  

json might not be the best choice for on-disk formats; The trouble it has with appending data is a good example of why this might be. Specifically, json objects have a syntax that means the whole object must be read and parsed in order to understand any part of it.

json可能不是磁盘格式的最佳选择;添加数据时遇到的麻烦就是一个很好的例子。具体来说,json对象的语法意味着必须读取和解析整个对象才能理解它的任何部分。

Fortunately, there are lots of other options. A particularly simple one is CSV; which is supported well by python's standard library. The biggest downside is that it only works well for text; it requires additional action on the part of the programmer to convert the values to numbers or other formats, if needed.

幸运的是,还有很多其他选择。一个特别简单的是CSV; python的标准库支持它。最大的缺点是它只适用于文本;如果需要,它需要程序员的额外操作将值转换为数字或其他格式。

Another option which does not have this limitation is to use a sqlite database, which also has built-in support in python. This would probably be a bigger departure from the code you already have, but it more naturally supports the 'modify a little bit' model you are apparently trying to build.

另一个没有这个限制的选项是使用一个sqlite数据库,它在python中也有内置的支持。这可能与您已有的代码有较大不同,但它更自然地支持您显然正在尝试构建的“修改一点”模型。

#3


7  

Append entry to the file contents if file exists, otherwise append the entry to an empty list and write in in the file:

如果文件存在,则将条目附加到文件内容,否则将条目附加到空列表并写入文件:

a = []
if not os.path.isfile(fname):
    a.append(entry)
    with open(fname, mode='w') as f:
        f.write(json.dumps(entry, indent=2))
else:
    with open(fname) as feedsjson:
        feeds = json.load(feedsjson)

    feeds.append(entry)
    with open(fname, mode='w') as f:
        f.write(json.dumps(feeds, indent=2))

#4


4  

Using a instead of w should let you update the file instead of creating a new one/overwriting everything in the existing file.

使用a代替w应该允许您更新文件而不是创建新文件/覆盖现有文件中的所有内容。

See this answer for a difference in the modes.

有关模式的不同,请参阅此答案。

#5


2  

One possible solution is do the concatenation manually, here is some useful code:

一种可能的解决方案是手动连接,这里有一些有用的代码:

import json
def append_to_json(_dict,path): 
    with open(path, 'ab+') as f:
    f.seek(0,2)                                #Go to the end of file    
    if f.tell() == 0 :                         #Check if file is empty
        f.write(json.dumps([_dict]).encode())  #If empty, write an array
    else :
        f.seek(-1,2)           
        f.truncate()                           #Remove the last character, open the array
        f.write(' , '.encode())                #Write the separator
        f.write(json.dumps(_dict).encode())    #Dump the dictionary
        f.write(']'.encode())                  #Close the array

You should be careful when editing the file outside the script not add any spacing at the end.

在脚本外部编辑文件时应该小心,不要在末尾添加任何间距。

#6


1  

You aren't ever writing anything to do with the data you read in. Do you want to be adding the data structure in feeds to the new one you're creating?

您不会写任何与您所读数据有关的内容。您是否希望将Feed中的数据结构添加到您正在创建的新数据中?

Or perhaps you want to open the file in append mode open(filename, 'a') and then add your string, by writing the string produced by json.dumps instead of using json.dump - but nneonneo points out that this would be invalid json.

或者你可能想要以附加模式open(filename,'a')打开文件然后添加你的字符串,通过写json.dumps而不是使用json.dump生成的字符串 - 但是nneonneo指出这将是无效的JSON。