UnicodeDecodeError al usar json.dumps ()

Tengo las siguientes cadenas en mi lista de python (tomadas de la línea de comandos):

>>> o['records'][5790] (5790, 'Vlv-Gate-Assy-Mdl-\xe1M1-2-\xe19/16-10K-BB Credit Memo ', 60, True, '40141613') >>> 

He intentado sugerencias como se mencionó aquí: ¿ Cambiar la encoding predeterminada de Python?

Además cambió la encoding predeterminada a utf-16 también. Pero aún así, json.dumps() lanzó una excepción de la siguiente manera:

 >>> write(o) Traceback (most recent call last): File "", line 1, in  File "okapi_create_master.py", line 49, in write o = json.dumps(output) File "C:\Python27\lib\json\__init__.py", line 231, in dumps return _default_encoder.encode(obj) File "C:\Python27\lib\json\encoder.py", line 201, in encode chunks = self.iterencode(o, _one_shot=True) File "C:\Python27\lib\json\encoder.py", line 264, in iterencode return _iterencode(o, 0) UnicodeDecodeError: 'utf8' codec can't decode byte 0xe1 in position 25: invalid continuation byte 

No se puede imaginar qué tipo de transformación se requiere para tales cadenas para que json.dumps() .

\xe1 no se puede decodificar usando la encoding utf-8, utf-16.

 >>> '\xe1'.decode('utf-8') Traceback (most recent call last): File "", line 1, in  File "C:\Python27\lib\encodings\utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0xe1 in position 0: unexpected end of data >>> '\xe1'.decode('utf-16') Traceback (most recent call last): File "", line 1, in  File "C:\Python27\lib\encodings\utf_16.py", line 16, in decode return codecs.utf_16_decode(input, errors, True) UnicodeDecodeError: 'utf16' codec can't decode byte 0xe1 in position 0: truncated data 

Prueba la encoding latin-1:

 >>> record = (5790, 'Vlv-Gate-Assy-Mdl-\xe1M1-2-\xe19/16-10K-BB Credit Memo ', ... 60, True, '40141613') >>> json.dumps(record, encoding='latin1') '[5790, "Vlv-Gate-Assy-Mdl-\\u00e1M1-2-\\u00e19/16-10K-BB Credit Memo ", 60, true, "40141613"]' 

O, especifique ensure_ascii=False , json.dumps para hacer que json.dumps no intente descodificar la cadena.

 >>> json.dumps(record, ensure_ascii=False) '[5790, "Vlv-Gate-Assy-Mdl-\xe1M1-2-\xe19/16-10K-BB Credit Memo ", 60, true, "40141613"]' 

Tuve un problema similar, y se me ocurrió el siguiente enfoque para garantizar unicodes o cadenas de bytes, de cualquiera de las entradas. En resumen, incluya y use las siguientes lambdas:

 # guarantee unicode string _u = lambda t: t.decode('UTF-8', 'replace') if isinstance(t, str) else t _uu = lambda *tt: tuple(_u(t) for t in tt) # guarantee byte string in UTF8 encoding _u8 = lambda t: t.encode('UTF-8', 'replace') if isinstance(t, unicode) else t _uu8 = lambda *tt: tuple(_u8(t) for t in tt) 

Aplicado a su pregunta:

 import json o = (5790, u"Vlv-Gate-Assy-Mdl-\xe1M1-2-\xe19/16-10K-BB Credit Memo ", 60, True, '40141613') as_json = json.dumps(_uu8(*o)) as_obj = json.loads(as_json) print "object\n ", o print "json (type %s)\n %s " % (type(as_json), as_json) print "object again\n ", as_obj 

=>

 object (5790, u'Vlv-Gate-Assy-Mdl-\xe1M1-2-\xe19/16-10K-BB Credit Memo ', 60, True, '40141613') json (type ) [5790, "Vlv-Gate-Assy-Mdl-\u00e1M1-2-\u00e19/16-10K-BB Credit Memo ", 60, true, "40141613"] object again [5790, u'Vlv-Gate-Assy-Mdl-\xe1M1-2-\xe19/16-10K-BB Credit Memo ', 60, True, u'40141613'] 

Aquí hay un poco más de razonamiento sobre esto .