Python 如何将数据附加到json文件?

Python 如何将数据附加到json文件?,python,json,Python,Json,我正在尝试创建一个函数,将条目添加到json文件中。最终,我想要一个看起来像 [{"name" = "name1", "url" = "url1"}, {"name" = "name2", "url" = "url2"}] 等等。这就是我所拥有的: def add(args): with open(DATA_FILENAME, mode='r', encoding='utf-8') as feedsjson: feeds = json.load(feedsjson)

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

[{"name" = "name1", "url" = "url1"}, {"name" = "name2", "url" = "url2"}]
等等。这就是我所拥有的:

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)
这会创建一个条目,例如
{“name”=“some name”,“url”=“some url”}
。但是,如果我再次使用这个
add
函数,使用不同的名称和url,第一个会被覆盖。我需要做什么才能将第二个(第三个…)条目附加到第一个条目

编辑:这个问题的第一个答案和评论已经指出了一个明显的事实,即我没有在写块中使用
提要
。不过,我不知道该怎么做。例如,以下显然不行:

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)

你从来没有写过任何与你读入的数据有关的东西。是否要将提要中的数据结构添加到正在创建的新提要中


或者您可能希望以追加模式
open(filename,'a')
打开文件,然后添加字符串,通过编写由
json.dumps
生成的字符串,而不是使用
json.dump
——但nneonneo指出,这将是无效的json。

使用
a
而不是
w
可以更新文件,而不是创建新文件/覆盖现有文件中的所有内容


有关模式的差异,请参阅。

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

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

with open(DATA_FILENAME, mode='w', encoding='utf-8') as f:
    json.dump([], f)
然后,您可以将新条目附加到此列表:

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)

请注意,由于每次调用
add
时都会重写文件的完整内容,因此执行起来会很慢。如果你在一个循环中调用它,考虑预先将所有的feed添加到一个列表中,然后一口气写出列表。

JSON可能不是磁盘格式的最佳选择;它在附加数据时遇到的麻烦就是一个很好的例子,说明了为什么会出现这种情况。具体来说,json对象的语法意味着必须读取和解析整个对象才能理解其中的任何部分

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


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

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

a = []
if not os.path.isfile(fname):
    a.append(entry)
    with open(fname, mode='w') as f:
        f.write(json.dumps(a, 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))

一种可能的解决方案是手动进行连接,下面是一些有用的 代码:


在脚本之外编辑文件时应小心,不要在末尾添加任何空格。

我有一些类似的代码,但每次都不会重写整个内容。这意味着要定期运行,并在数组末尾附加一个JSON条目

如果文件还不存在,它将创建它并将JSON转储到数组中。如果已经创建了文件,它将转到末尾,用一个
替换
]
放入新的JSON对象,然后用另一个
]

# Append JSON object to output file JSON array
fname = "somefile.txt"
if os.path.isfile(fname):
    # File exists
    with open(fname, 'a+') as outfile:
        outfile.seek(-1, os.SEEK_END)
        outfile.truncate()
        outfile.write(',')
        json.dump(data_dict, outfile)
        outfile.write(']')
else: 
    # Create file
    with open(fname, 'w') as outfile:
        array = []
        array.append(data_dict)
        json.dump(array, outfile)
这对我来说很有用:

with open('file.json', 'a') as outfile:
    outfile.write(json.dumps(data))
    outfile.write(",")
    outfile.close()

您只需从源文件导入数据、读取数据并保存要附加到变量的内容。然后打开目标文件,将其中的列表数据分配给一个新变量(假设这都是有效的JSON),然后在此列表变量上使用“append”函数并将第一个变量追加到它。Viola,您已经添加到JSON列表中。现在,只需使用新附加的列表(作为JSON)覆盖目标文件

“open”函数中的“a”模式在这里不起作用,因为它只会将所有内容附加到文件的末尾,这将使其成为无效的JSON格式

import jsonlines

object1 = {
               "name": "name1",
               "url": "url1"
          }

object2 = {
               "name": "name2",
               "url": "url2"
          }   


# filename.jsonl is the name of the file
with jsonlines.open("filename.jsonl", "a") as writer:   # for writing
    writer.write(object1)
    writer.write(object2)

with jsonlines.open('filename.jsonl') as reader:      # for reading
    for obj in reader:
        print(obj)             

访问以获取更多信息

您甚至没有在第二个块中使用
提要
,因此您当然会丢失以前的输出。哦,伙计。当然我显然太累了:(也许你可以看看这个问题。在列表中添加新数据更容易,而且不会破坏JSON格式。这是一个很好的尝试,但它会将无效的JSON写入文件(例如
{“a”:“b”}{“c”:“d”}
)。是的,我的意思是将feed中的数据结构添加到我正在创建的feed中。让我编辑这个问题以澄清这一点。谢谢。我正在尝试编写一个小型podcast聚合器。对于8-10行feed数据,sqlite数据库不是有点过火了吗?如果您的数据是统一的,您可以附加到一个类似json的文件中,只需将每行包含在您想要的对象中。然后,当您阅读时,只需将每一行解析为json对象。@Jonno\u FTW:使用这种格式的文件比sqlite要麻烦得多;在前一种情况下,您需要将所有对象累积到一个有用的结构中。虽然这只需要python的半打行,但仍然需要半打大于处理sqlite或CSV所需的1行。@SingleNegationElimination这假设您的数据是统一的,并且很好地适合SQL表。加上使用json,您可以获得比CSV字符串更多的类型。此外,您还可以使用
[json.loads(i)for i in open('somefile.json','r')。readlines()加载整个内容
它对我有用,你可以使用这个包在json文件上写和读谢谢。
提要
没有在你的代码示例中定义。它应该是原始文件的json.dump吗?这是我一直在尝试的,而且似乎不起作用。对不起。它的目的是在你添加时只替换原始文件中的写入块使用打开的
初始化文件(数据\u文件名,mode='r',encoding='utf-8')
import jsonlines

object1 = {
               "name": "name1",
               "url": "url1"
          }

object2 = {
               "name": "name2",
               "url": "url2"
          }   


# filename.jsonl is the name of the file
with jsonlines.open("filename.jsonl", "a") as writer:   # for writing
    writer.write(object1)
    writer.write(object2)

with jsonlines.open('filename.jsonl') as reader:      # for reading
    for obj in reader:
        print(obj)