Converti il ​​dizionario Python in un array JSON


98

Al momento ho questo dizionario, stampato 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 lo faccio:

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

Ottengo questo errore: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte


Il tuo problema sta qui:\xff
Benjamin Toueg

Risposte:


167

Se stai bene con i simboli non stampabili nel tuo json, aggiungi ensure_ascii=Falsea dumpscall.

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

Se ensure_asciiè false, il valore restituito sarà unicodeun'istanza soggetta alle normali regole di coercizione strdi Python unicodeinvece di essere sottoposto a escape in un ASCII str.


1
aggiungi indent=nalle opzioni per una bella stampa, dov'è nil numero di spazi da indentare
RTF

17

garantire_ascii = False in realtà rimanda il problema solo alla fase di decodifica:

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

In definitiva non è possibile archiviare byte grezzi in un documento JSON, quindi ti consigliamo di utilizzare alcuni mezzi per codificare in modo univoco una sequenza di byte arbitrari come una stringa ASCII, come 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'}

È possibile passare dati binari arbitrari (in modo inefficiente) in json utilizzando la codifica "latin1"
jfs

1
Potresti, suppongo, ma json è progettato / inteso per utilizzare utf-8.
Karl Knechtel

2
@ JFSebastian: In effetti, molto inefficiente rispetto a b64encode. Ad esempio, per la stringa di 256 caratteri 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 usi Python 2, non dimenticare di aggiungere il commento sulla codifica del file UTF-8 sulla prima riga del tuo script.

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

Questo risolverà alcuni problemi Unicode e ti semplificherà la vita.


2

Una possibile soluzione che uso è usare python3. Sembra risolvere molti problemi di utf.

Ci scusiamo per la risposta tardiva, ma potrebbe aiutare le persone in futuro.

Per esempio,

#!/usr/bin/env python3
import json
# your code follows

4
Certo, hai dannatamente ragione, Python 3 ha risolto molti problemi di codifica. Ma questa non è la risposta a questa domanda. È etichettato esplicitamente con python-2.7. Quindi quello che stai dicendo è qualcosa del genere: Non c'è un aspirapolvere integrato nella tua vecchia macchina. Quindi per favore compra una nuova macchina invece di aggiungere un aspirapolvere nella tua vecchia macchina.
colidyre
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.