Converter dicionário Python em matriz JSON

98

Atualmente tenho este dicionário, impresso 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}

Quando eu faço isso:

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

Eu recebo este erro: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

HyperDevil
fonte
Seu problema está aqui:\xff
Benjamin Toueg

Respostas:

167

Se você estiver satisfeito com símbolos não imprimíveis em seu json, adicione ensure_ascii=Falseà dumpschamada.

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

Se ensure_asciifor falso, o valor de retorno será uma unicodeinstância sujeita ao Python normal strpara unicode regras de coerção em vez de ser escapado para um ASCII str.

Kmerenkov
fonte
1
adicione indent=nàs opções de impressão bonita, onde né o número de espaços para recuar
RTF
17

garantir_ascii = False realmente apenas adia o problema para o estágio de decodificação:

>>> 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

Em última análise, você não pode armazenar bytes brutos em um documento JSON, então você vai querer usar alguns meios de codificar inequivocamente uma sequência de bytes arbitrários como uma string 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
fonte
Você poderia passar dados binários arbitrários (ineficientemente) em json usando a codificação 'latin1'
jfs
1
Você poderia, suponho, mas json foi projetado / projetado para usar utf-8.
Karl Knechtel
2
@JFSebastian: De fato, muito ineficiente em comparação com b64encode. Por exemplo, para a cadeia 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

Se você usa Python 2, não se esqueça de adicionar o comentário de codificação do arquivo UTF-8 na primeira linha do seu script.

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

Isso corrigirá alguns problemas de Unicode e tornará sua vida mais fácil.

justiça
fonte
2

Uma possível solução que uso é usar o python3. Parece resolver muitos problemas de utf.

Desculpe pela resposta tardia, mas pode ajudar as pessoas no futuro.

Por exemplo,

#!/usr/bin/env python3
import json
# your code follows
Ralph Yozzo
fonte
4
Claro, você está certo, Python 3 resolveu muitos problemas de codificação. Mas essa não é a resposta a essa pergunta. Está explicitamente marcado com python-2.7. Então, o que você está dizendo é algo assim: não há aspirador de pó embutido em seu carro antigo. Portanto, compre um carro novo em vez de colocar um aspirador de pó em seu carro antigo.
colidira de