Convierta el diccionario de Python en una matriz JSON

98

Actualmente tengo este diccionario, impreso usando pprint:

{'AlarmExTempHum': '\x00\x00\x00\x00\x00\x00\x00\x00',  
'AlarmIn': 0,  
'AlarmOut': '\x00\x00',  
'AlarmRain': 0,  
'AlarmSoilLeaf': '\x00\x00\x00\x00',  
'BarTrend': 60,  
'BatteryStatus': 0,  
'BatteryVolts': 4.751953125,  
'CRC': 55003,
'EOL': '\n\r',
'ETDay': 0,
'ETMonth': 0,
'ETYear': 0,
'ExtraHum1': None,
'ExtraHum2': None,
'ExtraHum3': None,
'ExtraHum4': None,
'ExtraHum5': None,
'ExtraHum6': None,
'ExtraHum7': None,
'ExtraTemp1': None,
'ExtraTemp2': None,
'ExtraTemp3': None,
'ExtraTemp4': None,
'ExtraTemp5': None,
'ExtraTemp6': None,
'ExtraTemp7': None,
'ForecastIcon': 2,
'ForecastRuleNo': 122,
'HumIn': 31,
'HumOut': 94,
'LOO': 'LOO',
'LeafTemps': '\xff\xff\xff\xff',
'LeafWetness': '\xff\xff\xff\x00',
'NextRec': 37,
'PacketType': 0,
'Pressure': 995.9363359295631,
'RainDay': 0.0,
'RainMonth': 0.0,
'RainRate': 0.0,
'RainStorm': 0.0,
'RainYear': 2.8,
'SoilMoist': '\xff\xff\xff\xff',
'SoilTemps': '\xff\xff\xff\xff',
'SolarRad': None,
'StormStartDate': '2127-15-31',
'SunRise': 849,
'SunSet': 1611,
'TempIn': 21.38888888888889,
'TempOut': 0.8888888888888897,
'UV': None,
'WindDir': 219,
'WindSpeed': 3.6,
'WindSpeed10Min': 3.6}

Cuando hago esto:

import json
d = (my dictionary above)
jsonarray = json.dumps(d)

Me sale este error: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

HyperDevil
fuente
Su problema radica aquí:\xff
Benjamin Toueg

Respuestas:

167

Si está de acuerdo con los símbolos no imprimibles en su json, agregue ensure_ascii=Falsepara dumpsllamar.

>>> json.dumps(your_data, ensure_ascii=False)

Si ensure_asciies falso, el valor de retorno será una unicodeinstancia sujeta a las reglas normales strde unicodecoerción de Python en lugar de escapar a un ASCII str.

kmerenkov
fuente
1
agregar indent=na las opciones de impresión bonita, donde nestá el número de espacios para sangrar
RTF
17

asegurar_ascii = Falso realmente solo pospone el problema a la etapa de decodificación:

>>> dict2 = {'LeafTemps': '\xff\xff\xff\xff',}
>>> json1 = json.dumps(dict2, ensure_ascii=False)
>>> print(json1)
{"LeafTemps": "����"}
>>> json.loads(json1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/json/__init__.py", line 328, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 365, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 381, in raw_decode
    obj, end = self.scan_once(s, idx)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

En última instancia, no puede almacenar bytes sin procesar en un documento JSON, por lo que querrá usar algún medio para codificar sin ambigüedades una secuencia de bytes arbitrarios como una cadena ASCII, como base64.

>>> import json
>>> from base64 import b64encode, b64decode
>>> my_dict = {'LeafTemps': '\xff\xff\xff\xff',} 
>>> my_dict['LeafTemps'] = b64encode(my_dict['LeafTemps'])
>>> json.dumps(my_dict)
'{"LeafTemps": "/////w=="}'
>>> json.loads(json.dumps(my_dict))
{u'LeafTemps': u'/////w=='}
>>> new_dict = json.loads(json.dumps(my_dict))
>>> new_dict['LeafTemps'] = b64decode(new_dict['LeafTemps'])
>>> print new_dict
{u'LeafTemps': '\xff\xff\xff\xff'}
rkday
fuente
Podría pasar datos binarios arbitrarios (de manera ineficiente) en json usando la codificación '
latin1
1
Podría, supongo, pero json está diseñado / destinado a usar utf-8.
Karl Knechtel
2
@JFSebastian: De hecho, muy ineficiente en comparación con b64encode. Por ejemplo, para la cadena de 256 caracteres s = ''.join(chr(i) for i in xrange(256)), len(json.dumps(b64encode(s))) == 346vs len(json.dumps(s.decode('latin1'))) == 1045.
martineau
10

Si usa Python 2, no olvide agregar el comentario de codificación del archivo UTF-8 en la primera línea de su secuencia de comandos.

# -*- coding: UTF-8 -*-

Esto solucionará algunos problemas de Unicode y le facilitará la vida.

justicia
fuente
2

Una posible solución que utilizo es usar python3. Parece resolver muchos problemas de utf.

Perdón por la respuesta tardía, pero puede ayudar a las personas en el futuro.

Por ejemplo,

#!/usr/bin/env python3
import json
# your code follows
Ralph Yozzo
fuente
4
Seguro, tienes toda la razón, Python 3 resolvió muchos problemas de codificación. Pero esa no es la respuesta a esa pregunta. Está etiquetado explícitamente con python-2.7. Entonces, lo que está diciendo es algo como esto: no hay una aspiradora incorporada en su automóvil viejo. Por lo tanto, compre un automóvil nuevo en lugar de agregar una aspiradora en su automóvil viejo.
colidyre