我有一个(有效的)JSON文件包含JSON对象,每个对象占用一个文件行。这些JSON对象映射到Python dicts,并按数字ID按升序排列。
我正在编写一个接受三个参数的更新方法:(1)文件路径,(2)有序ID列表,以及(3)带有更新值的JSON对象属性的dict,并遍历文件(以r+
模式打开),在ID列表中查找JSON对象,然后使用dict中的值更新对象属性,并将对象写回文件。
每个对象占用一行,并以逗号分隔。如果所需的ID在一行中,那么在写入文件之前,指针将向后移动线的长度到开头。但问题是新的对象线可能更长,在这种情况下它会覆盖该对象后面的另一个对象的线。
我只需要替换我感兴趣的行,但不要覆盖后续行。任何帮助将不胜感激。
以下是代码:
def update_JSON_file( self, file_path, obj_IDs, obj_props ):
decoder = json.JSONDecoder()
with io.open( file_path, 'r+', encoding='utf=8' ) as file:
IDs_iter = iter( obj_IDs )
for line in file:
ID = IDs_iter.next()
if str( ID ) in line:
JSON_obj = decoder.raw_decode( line )[0]
for key in props.keys():
JSON_obj[key] = props[key]
JSON_obj = json.dumps( JSON_obj, ensure_ascii=False )
if '},\n' in line: JSON_obj += ',\n'
JSON_obj = unicode( JSON_obj )
file.seek( file.tell() - len( line ) )
file.write( JSON_obj )
答案 0 :(得分:1)
你无法做你想做的事,因为你只能通过外科手术替换文件中的固定长度记录。您无法使用更长或更短的内容替换该行,因为文件不会将数据存储为单独的行。
此外,您的代码没有考虑到在某些平台上(如在Windows上)文本文件中的行由两个字符分隔,在Python中可以表示为\r\n
,但这些行结尾是翻译成单个字符\n
。您的行长计算并未考虑到这一点。
您必须在该行之后重写所有内容。你最好使用数据库; sqlite3
与Python捆绑在一起,看一下。
答案 1 :(得分:0)
def update_JSON_file( self, file_path, obj_IDs, props ):
decoder = json.JSONDecoder()
with io.open( file_path, 'r+', encoding='utf=8' ) as files:
IDs_iter = iter( obj_IDs )
fl = files.read().splitlines(True)
ID = IDs_iter.next()
for i,line in enumerate(fl):
# ID = IDs_iter.next()
# I think the 'ID' should be initialized out of the loop
# and iterated only if the condition is true
if str(ID) in line:
JSON_obj = decoder.raw_decode(line)[0]
for key in props.keys():
JSON_obj[key] = props[key]
JSON_obj = json.dumps( JSON_obj, ensure_ascii=False )
if '},\n' in line: JSON_obj += ',\n'
JSON_obj = unicode( JSON_obj )
fl[i] = JSON_obj
try:
ID = IDs_iter.next()
except StopIteration:
break
files.seek(0)
files.write(''.join(fl))
return True