¿Cómo anexar datos a un archivo json?

Estoy intentando crear una función que agregaría entradas a un archivo json. Finalmente, quiero un archivo que se parece a

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

Esto es lo que tengo:

 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) 

Esto crea una entrada como {"name"="some name", "url"="some url"} . Pero, si uso esta función de add nuevamente, con un nombre y una URL diferentes, la primera se sobrescribe. ¿Qué debo hacer para que se agregue una segunda (tercera …) entrada a la primera?

EDITAR : Las primeras respuestas y comentarios a esta pregunta han señalado el hecho obvio de que no estoy utilizando feeds en el bloque de escritura. Aunque no veo cómo hacer eso. Por ejemplo, lo siguiente aparentemente no lo hará:

 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) 

json podría no ser la mejor opción para los formatos en disco; El problema que tiene con los datos adjuntos es un buen ejemplo de por qué esto podría ser. Específicamente, los objetos json tienen una syntax que significa que todo el objeto debe leerse y analizarse para comprender cualquier parte de él.

Afortunadamente, hay muchas otras opciones. Una particularmente simple es CSV; que es bien soportado por la biblioteca estándar de python. El mayor inconveniente es que solo funciona bien para texto; se requiere una acción adicional por parte del progtwigdor para convertir los valores a números u otros formatos, si es necesario.

Otra opción que no tiene esta limitación es usar una base de datos sqlite, que también tiene soporte incorporado en Python. Probablemente, esto supondría una diferencia mayor con respecto al código que ya tiene, pero es más natural que sea compatible con el modelo de “modificar un poco” que aparentemente está intentando construir.

Probablemente desee utilizar una lista JSON en lugar de un diccionario como elemento de nivel superior.

Entonces, inicialice el archivo con una lista vacía:

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

Luego, puede agregar nuevas entradas a esta lista:

 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) 

Tenga en cuenta que la ejecución será lenta porque reescribirá el contenido completo del archivo cada vez que llame a add . Si lo llama en un bucle, considere agregar todos los feeds a una lista de antemano, y luego escribir la lista de una sola vez.

Agregue la entrada al contenido del archivo si el archivo existe; de ​​lo contrario, agregue la entrada a una lista vacía y escriba en el archivo:

 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)) 

Usar a lugar de w debería permitirle actualizar el archivo en lugar de crear uno nuevo / sobrescribir todo en el archivo existente.

Vea esta respuesta para una diferencia en los modos.

Una posible solución es hacer la concatenación manualmente, aquí hay algunos códigos útiles:

 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 

Debe tener cuidado cuando edite el archivo fuera de la secuencia de comandos, no agregue ningún espacio al final.

Nunca escribirá nada que ver con los datos que lee. ¿Desea agregar la estructura de datos en las fonts a la nueva que está creando?

O tal vez desee abrir el archivo en modo de adición open(filename, 'a') y luego agregar su cadena, escribiendo la cadena producida por json.dumps lugar de usar json.dump , pero nneonneo señala que esto no sería válido json

Tengo un código similar, pero no reescribe todo el contenido cada vez. Esto está destinado a ejecutarse periódicamente y agregar una entrada JSON al final de una matriz.

Si el archivo aún no existe, lo crea y descarga el JSON en una matriz. Si el archivo ya se ha creado, va al final, reemplaza el ] con a , suelta el nuevo objeto JSON y luego lo cierra de nuevo con otro ]

 # 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) 

introduzca la descripción del enlace aquí

Tal vez podrías revisar esta pregunta. Es más fácil agregar nuevos datos en una lista y no rompería su formato JSON.