2012-03-06 23 views
15

Estoy usando json.dump() y json.load() para guardar/leer un diccionario de cadenas en/desde el disco. El problema es que no puedo tener ninguna de las cadenas en Unicode. Parecen estar en Unicode, sin importar cómo configuro los parámetros para volcar/cargar (incluyendo Ensure_ascii y codificación).Forzar el módulo Python json para que funcione con ASCII

+5

favor publicar su código actual y los mensajes de error que está recibiendo. Gracias. – bernie

+0

¿Qué quiere decir con "en Unicode"? ¿Estás hablando del escape de caracteres no ASCII a escapes '\ u1234'? Si es así, ¿por qué esta codificación no es aceptable? Es JSON perfectamente válido que cualquier analizador debe aceptar; hay caracteres que * deben * estar codificados en este formato incluso si, en general, está dejando caracteres no ASCII sin guardar. – bobince

+1

Porque JSON es de forma nativa formato utf-8. Python's json.loads() acepta símbolos no ascii y los analiza en cadenas Unicode. jsob.loads() analiza todas las cadenas en el tipo de Python 'unicode', no 'str'. ¡Pero json.dumps() escapa ** todos los ** símbolos no ascii! Entonces, string! = Json.dumps (json.loads (string)) –

Respuesta

20

Si sólo están tratando con objetos JSON simples, usted puede utilizar el siguiente:

def ascii_encode_dict(data): 
    ascii_encode = lambda x: x.encode('ascii') 
    return dict(map(ascii_encode, pair) for pair in data.items()) 

json.loads(json_data, object_hook=ascii_encode_dict) 

Aquí es un ejemplo de cómo funciona:

>>> json_data = '{"foo": "bar", "bar": "baz"}' 
>>> json.loads(json_data)        # old call gives unicode 
{u'foo': u'bar', u'bar': u'baz'} 
>>> json.loads(json_data, object_hook=ascii_encode_dict) # new call gives str 
{'foo': 'bar', 'bar': 'baz'} 

This answer obras para una más compleja JSON estructura, y da una buena explicación sobre el parámetro object_hook. También hay otra respuesta que toma recursivamente el resultado de una llamada json.loads() y convierte todas las cadenas Unicode en cadenas de bytes.

+1

Es posible que desee cambiar la línea a 'ascii_encode = lambda x: x.encode ('ascii', 'ignore') si los datos tienen muchos caracteres cuya 'ord> 128'. – mac389

+0

El enlace a la otra respuesta para la estructura JSON más compleja era exactamente lo que necesitaba. – adg

11

Y si el objeto JSON es una mezcla de tipos de datos, no sólo las cadenas Unicode, se puede utilizar esta expresión:

def ascii_encode_dict(data): 
    ascii_encode = lambda x: x.encode('ascii') if isinstance(x, unicode) else x 
    return dict(map(ascii_encode, pair) for pair in data.items()) 
Cuestiones relacionadas