¿Cómo escribo datos JSON en un archivo?

Tengo datos JSON almacenados en la variable data.

Quiero escribirlo en un archivo de texto para probarlo y no tener que coger los datos del servidor cada vez.

Actualmente, estoy probando esto:

obj = open('data.txt', 'wb')
obj.write(data)
obj.close

Y estoy recibiendo el error:

TypeError: must be string or buffer, not dict

¿Cómo se arregla esto?

Solución

Te olvidaste de la parte real de JSON - data es un diccionario y aún no está codificado en JSON. Escríbelo así para una 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, Python 3 y soporte UTF-8), puedes escribir un archivo más bonito con

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

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

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 sencillo en Python 3:

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

En Windows, el argumento encoding='utf-8' para open sigue siendo necesario.

Para evitar el almacenamiento de una copia codificada de los datos en la memoria (resultado de dumps) y para dar salida a bytestrings codificados en utf8 tanto en Python 2 como en 3, utilice:

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

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


Lectura y tamaño:

El uso de ensure_ascii=False proporciona una mejor legibilidad y un menor tamañ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

Mejora aún más la legibilidad añadiendo las banderas indent=4, sort_keys=True (como sugiere dinos66) a los argumentos de dump o dumps. De este modo, obtendrá una estructura ordenada y bien indentada en el archivo json a costa de un tamaño de archivo ligeramente mayor.

Comentarios (18)

Yo respondería con una ligera modificación con las respuestas antes mencionadas y es escribir un archivo JSON embellecido que los ojos humanos puedan leer mejor. Para ello, pase sort_keys como True y indent con 4 caracteres de espacio y usted es bueno para ir. También asegúrese de que los códigos ascii no se escriban en su archivo JSON:

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)
Comentarios (5)