Dump to JSON agrega comillas dobles adicionales y escape de comillas

86

Estoy recuperando datos de Twitter con una herramienta de Python y los vuelco en formato JSON a mi disco. Noté un escape involuntario de toda la cadena de datos de un tweet entre comillas dobles. Además, todas las comillas dobles del formato JSON real se escapan con una barra invertida.

Se ven así:

"{\" created_at \ ": \" Vie 08 de agosto 11:04:40 +0000 2014 \ ", \" id \ ": 497699913925292032,

¿Cómo evito eso? Debería ser:

{"created_at": "Vie 08 de agosto 11:04:40 + 0000 2014" .....

Mi código de salida de archivo se ve así:

with io.open('data'+self.timestamp+'.txt', 'a', encoding='utf-8') as f:
            f.write(unicode(json.dumps(data, ensure_ascii=False)))
            f.write(unicode('\n'))

El escape no intencionado causa problemas al leer el archivo JSON en un paso de procesamiento posterior.

toobee
fuente

Respuestas:

140

Estás codificando dos veces tus cadenas JSON. yadata es una cadena JSON y no necesita codificarse nuevamente :

>>> import json
>>> not_encoded = {"created_at":"Fri Aug 08 11:04:40 +0000 2014"}
>>> encoded_data = json.dumps(not_encoded)
>>> print encoded_data
{"created_at": "Fri Aug 08 11:04:40 +0000 2014"}
>>> double_encode = json.dumps(encoded_data)
>>> print double_encode
"{\"created_at\": \"Fri Aug 08 11:04:40 +0000 2014\"}"

Simplemente escríbalos directamente en su archivo:

with open('data{}.txt'.format(self.timestamp), 'a') as f:
    f.write(data + '\n')
Martijn Pieters
fuente
f.write (data + '\ n') - se correlaciona con - data = encoded_data - de su ejemplo.
Rich Elswick
@RichElswick, el OP usa la variable data, que contiene datos JSON ya codificados, así que sí, usé el nombre de la variable encoded_datapara ilustrar lo que estaba sucediendo.
Martijn Pieters
9

Otra situación en la que puede ocurrir este escape no deseado es si intenta utilizar json.dump () en la salida preprocesada de json.dumps (). Por ejemplo

import json, sys
json.dump({"foo": json.dumps([{"bar": 1}, {"baz": 2}])},sys.stdout)

resultará en

{"foo": "[{\"bar\": 1}, {\"baz\": 2}]"}

Para evitar esto, debe pasar diccionarios en lugar de la salida de json.dumps (), por ejemplo

json.dump({"foo": [{"bar": 1}, {"baz": 2}]},sys.stdout)

que produce el deseado

{"foo": [{"bar": 1}, {"baz": 2}]}

(¿Por qué preprocesarías la lista interna con json.dumps (), preguntas? Bueno, tenía otra función que estaba creando esa lista interna a partir de otras cosas, y pensé que tendría sentido devolver un objeto json de esa función ... mal.)

Mike Maxwell
fuente