¿Cómo escribo datos JSON en un archivo?

Resuelto user1530318 asked hace 12 años • 16 respuestas

¿Cómo escribo datos JSON almacenados en el diccionario dataen un archivo?

f = open('data.json', 'wb')
f.write(data)

Esto da el error:

TypeError: debe ser una cadena o un búfer, no un dict

user1530318 avatar Sep 07 '12 05:09 user1530318
Aceptado

dataes un diccionario de Python. Debe codificarse como JSON antes de escribirlo.

Utilice esto para máxima compatibilidad (Python 2 y 3):

import json
with open('data.json', 'w') as f:
    json.dump(data, f)

En un sistema moderno (es decir, compatibilidad con Python 3 y UTF-8), puede escribir un archivo mejor usando:

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)

Ver jsondocumentación.

phihag avatar Sep 06 '2012 22:09 phihag

Para obtener un archivo codificado en utf8 en lugar de codificado en ascii en la respuesta aceptada para Python 2, use:

import io, json
with io.open('data.txt', 'w', encoding='utf-8') as f:
  f.write(json.dumps(data, ensure_ascii=False))

El código es más simple en Python 3:

import json
with open('data.txt', 'w') as f:
  json.dump(data, f, ensure_ascii=False)

En Windows, el encoding='utf-8'argumento to opensigue siendo necesario.

Para evitar almacenar una copia codificada de los datos en la memoria (resultado de dumps) y generar cadenas de bytes codificadas en utf8 tanto en Python 2 como en Python 3, use:

import json, codecs
with open('data.txt', 'wb') as f:
    json.dump(data, codecs.getwriter('utf-8')(f), ensure_ascii=False)

La codecs.getwriterllamada es redundante en Python 3 pero necesaria para Python 2


Legibilidad y tamaño:

El uso de ensure_ascii=Falseproporciona una mejor legibilidad y un tamaño más pequeño:

>>> json.dumps({'price': '€10'})
'{"price": "\\u20ac10"}'
>>> json.dumps({'price': '€10'}, ensure_ascii=False)
'{"price": "€10"}'

>>> len(json.dumps({'абвгд': 1}))
37
>>> len(json.dumps({'абвгд': 1}, ensure_ascii=False).encode('utf8'))
17

Mejore aún más la legibilidad agregando banderas indent=4, sort_keys=True(como lo sugiere dinos66 ) a los argumentos de dumpo dumps. De esta manera, obtendrá una estructura ordenada con buena sangría en el archivo json a costa de un tamaño de archivo ligeramente mayor.

Antony Hatchkins avatar Feb 14 '2013 08:02 Antony Hatchkins

Respondería con una ligera modificación a las respuestas antes mencionadas y es escribir un archivo JSON embellecido que los ojos humanos puedan leer mejor. Para esto, pase sort_keyscomo Truey indentcon 4 caracteres de espacio y listo. También asegúrese de asegurarse de que los códigos ascii no se escriban en su archivo JSON:

with open('data.txt', 'w') as out_file:
     json.dump(json_data, out_file, sort_keys = True, indent = 4,
               ensure_ascii = False)
ambodi avatar Dec 25 '2013 20:12 ambodi

Leer y escribir archivos JSON con Python 2+3; funciona con unicode

# -*- coding: utf-8 -*-
import json

# Make it work for Python 2+3 and with Unicode
import io
try:
    to_unicode = unicode
except NameError:
    to_unicode = str

# Define data
data = {'a list': [1, 42, 3.141, 1337, 'help', u'€'],
        'a string': 'bla',
        'another dict': {'foo': 'bar',
                         'key': 'value',
                         'the answer': 42}}

# Write JSON file
with io.open('data.json', 'w', encoding='utf8') as outfile:
    str_ = json.dumps(data,
                      indent=4, sort_keys=True,
                      separators=(',', ': '), ensure_ascii=False)
    outfile.write(to_unicode(str_))

# Read JSON file
with open('data.json') as data_file:
    data_loaded = json.load(data_file)

print(data == data_loaded)

Explicación de los parámetros de json.dump:

  • indent: Utilice 4 espacios para sangrar cada entrada, por ejemplo, cuando se inicia un nuevo dictado (de lo contrario, todo estará en una línea),
  • sort_keys: ordena las claves de los diccionarios. Esto es útil si desea comparar archivos json con una herramienta de diferenciación/ponerlos bajo control de versiones.
  • separators: Para evitar que Python agregue espacios en blanco al final

con un paquete

Echa un vistazo a mi paquete de utilidades mpupara encontrar uno súper simple y fácil de recordar:

import mpu.io
data = mpu.io.read('example.json')
mpu.io.write('example.json', data)

Archivo JSON creado

{
    "a list":[
        1,
        42,
        3.141,
        1337,
        "help",
        "€"
    ],
    "a string":"bla",
    "another dict":{
        "foo":"bar",
        "key":"value",
        "the answer":42
    }
}

Terminaciones de archivos comunes

.json

Alternativas

  • CSV: formato súper simple ( lectura y escritura )
  • JSON: Agradable para escribir datos legibles por humanos; MUY comúnmente utilizado ( lectura y escritura )
  • YAML: YAML es un superconjunto de JSON, pero más fácil de leer ( lectura y escritura , comparación de JSON y YAML )
  • pickle: un formato de serialización de Python ( lectura y escritura )
  • MessagePack ( paquete Python ): representación más compacta ( lectura y escritura )
  • HDF5 ( paquete Python ): ideal para matrices ( lectura y escritura )
  • XML: también existe *suspiro* ( lectura y escritura )

Para su aplicación, lo siguiente puede ser importante:

  • Soporte por otros lenguajes de programación.
  • Rendimiento en lectura/escritura
  • Compacidad (tamaño de archivo)

Ver también: Comparación de formatos de serialización de datos

En caso de que esté buscando una forma de crear archivos de configuración, es posible que desee leer mi breve artículo Archivos de configuración en Python.

Martin Thoma avatar Jun 13 '2016 16:06 Martin Thoma

Para aquellos de ustedes que están tratando de deshacerse del griego u otros idiomas "exóticos" como yo, pero que también tienen problemas (errores Unicode) con caracteres extraños como el símbolo de la paz (\u262E) u otros que a menudo están contenidos en datos con formato json. como el de Twitter, la solución podría ser la siguiente (sort_keys es obviamente opcional):

import codecs, json
with codecs.open('data.json', 'w', 'utf8') as f:
     f.write(json.dumps(data, sort_keys = True, ensure_ascii=False))
dinos66 avatar Jul 10 '2015 14:07 dinos66