使用Python字典构造JSON时列表元素被覆盖的解决方法
解决Python生成指定JSON结构时的字典覆盖问题
需求与问题详情
目标JSON结构
{ "filelist": [ { "filename": "file1.txt", "oof": 0 }, { "filename": "file2.txt", "oof": 0 }, { "filename": "file3.txt", "oof": 0 } ] }
现有实现代码
for line in listoflines: mysmalldict ["filename"] = line.strip("\n") mysmalldict ["oof"] = 0 dictcollector.append(mysmalldict) mybigdict["filelist"] = dictcollector print(json.dumps(mybigdict))
异常现象
执行代码后,生成的JSON中所有filename字段均被最后一条数据file3.txt覆盖,结果如下:
{ "filelist": [ { "filename": "file3.txt", "oof": 0 }, { "filename": "file3.txt", "oof": 0 }, { "filename": "file3.txt", "oof": 0 } ] }
不符合需求的错误方案
曾找到的解决方案生成的是字符串数组而非字典数组,无法满足结构要求:
{ "filelist": [ '{ "filename": "file3.txt", "oof": 0 }', '{ "filename": "file3.txt", "oof": 0 }', '{ "filename": "file3.txt", "oof": 0 }' ] }
问题根源
Python中字典是可变对象,你在循环中反复修改同一个mysmalldict实例,然后将其引用添加到列表dictcollector中。列表存储的是字典的内存地址而非副本,因此循环结束时,所有列表元素指向的都是最后一次修改后的同一个字典,导致所有filename显示为最后一条数据。
正确实现方法
方法1:循环内创建新字典
每次迭代都新建一个字典实例,避免复用同一个对象:
import json listoflines = ["file1.txt\n", "file2.txt\n", "file3.txt\n"] dictcollector = [] mybigdict = {} for line in listoflines: # 每次循环生成新的小字典 mysmalldict = {} mysmalldict["filename"] = line.strip("\n") mysmalldict["oof"] = 0 dictcollector.append(mysmalldict) mybigdict["filelist"] = dictcollector print(json.dumps(mybigdict, indent=4))
方法2:使用列表推导式(简洁写法)
如果listoflines已处理为无换行的文件名列表,可直接用列表推导式生成字典数组:
import json listoflines = ["file1.txt", "file2.txt", "file3.txt"] mybigdict = { "filelist": [{"filename": fname, "oof": 0} for fname in listoflines] } print(json.dumps(mybigdict, indent=4))
预期输出
两种方法均会生成符合需求的目标JSON结构:
{ "filelist": [ { "filename": "file1.txt", "oof": 0 }, { "filename": "file2.txt", "oof": 0 }, { "filename": "file3.txt", "oof": 0 } ] }
内容的提问来源于stack exchange,提问作者Gazelle
相关产品推荐
相关产品推荐

