Convertir le dictionnaire Python en tableau JSON

98

Actuellement, j'ai ce dictionnaire, imprimé en utilisant 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}

Quand je fais ça:

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

J'obtiens cette erreur: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

HyperDevil
la source
Votre problème se trouve ici:\xff
Benjamin Toueg

Réponses:

167

Si vous êtes d'accord avec les symboles non imprimables dans votre json, ajoutez ensure_ascii=Falseà l' dumpsappel.

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

Si ensure_asciiest false, alors la valeur de retour sera une unicodeinstance soumise à Python normal straux unicode règles de coercition au lieu d'être échappée à un ASCII str.

kmerenkov
la source
1
ajouter indent=naux options de pretty print, où nest le nombre d'espaces à indenter
RTF
17

assurer_ascii = False ne reporte vraiment le problème qu'à l'étape de décodage:

>>> 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 fin de compte, vous ne pouvez pas stocker des octets bruts dans un document JSON, vous voudrez donc utiliser un moyen d'encoder sans ambiguïté une séquence d'octets arbitraires sous forme de chaîne ASCII - telle que 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
la source
Vous pouvez passer des données binaires arbitraires (de manière inefficace) dans json en utilisant le codage 'latin1'
jfs
1
Vous pourriez, je suppose, mais json est conçu / destiné à utiliser utf-8.
Karl Knechtel
2
@JFSebastian: En effet, très inefficace par rapport à b64encode. Par exemple, pour la chaîne de caractères 256 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 vous utilisez Python 2, n'oubliez pas d'ajouter le commentaire d'encodage de fichier UTF-8 sur la première ligne de votre script.

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

Cela résoudra certains problèmes Unicode et vous facilitera la vie.

Justice
la source
2

Une solution possible que j'utilise est d'utiliser python3. Il semble résoudre de nombreux problèmes utf.

Désolé pour la réponse tardive, mais cela pourrait aider les gens à l'avenir.

Par exemple,

#!/usr/bin/env python3
import json
# your code follows
Ralph Yozzo
la source
4
Bien sûr, vous avez parfaitement raison, Python 3 a résolu de nombreux problèmes d'encodage. Mais ce n'est pas la réponse à cette question. Il est explicitement étiqueté avec python-2.7. Donc, ce que vous dites est quelque chose comme ceci: il n'y a pas d'aspirateur intégré dans votre vieille voiture. Veuillez donc acheter une nouvelle voiture au lieu d'ajouter un aspirateur dans votre ancienne voiture.
colidyre