2013-02-02 11 views
64

Obecnie mam ten słownik, drukowanymi pprint:Konwersja słownika Pythona do tablicy JSON

{'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} 

Kiedy to zrobić:

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

otrzymuję ten błąd: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

+0

Twój problem leży tutaj: '\ xff' –

Odpowiedz

119

Jeśli są dobrze z nie drukowalnymi symbolami w twoim jsonie, następnie dodaj ensure_ascii=False do dumps połączenia.

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

If ensure_ascii is false, then the return value will be a unicode instance subject to normal Python str to unicode coercion rules instead of being escaped to an ASCII str .

+0

dodaj' indent = n' do opcji do ładnego druku, gdzie 'n' to liczba spacji do wcięcia – RTF

12

ensure_ascii = False naprawdę tylko odsuwa problem na etapie dekodowania:

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

Ostatecznie nie można przechowywać surowe bajty w dokumencie JSON, więc będziemy chcieli wykorzystać niektóre sposoby jednoznacznego kodowania ciągu dowolnych bajtów jako ciągu ASCII - na przykład 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'} 
+0

Możesz przekazać dowolne dane binarne (nieefektywnie) w jsonie [ używając kodowania "latin1"] (http://ideone.com/VrOtxm) – jfs

+1

Moglibyście, jak sądzę, ale json został zaprojektowany/zamierzony do używania utf-8. –

+2

@ J.F.Sebastian: Rzeczywiście, _very_ nieskuteczne w porównaniu do 'b64encode'. Na przykład dla ciągu 256 znaków 's = '' .join (chr (i) dla i w xrange (256))', 'len (json.dumps (b64encode (s)) == 346' vs' len (json.dumps (s.decode ('latin1'))) == 1045'. – martineau

2

Jednym z możliwych rozwiązań, których używam jest użycie python3. Wydaje się, że rozwiązuje wiele problemów związanych z utf.

Przepraszamy za późną odpowiedź, ale może pomóc ludziom w przyszłości.

Na przykład

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

Oczywiście, masz rację, Python 3 rozwiązał wiele problemów z kodowaniem. Ale to nie jest odpowiedź na to pytanie. Jest wyraźnie oznaczony pythonem-2.7. Więc to, co mówisz, jest coś takiego: W twoim starym samochodzie nie ma wbudowanego odkurzacza. Więc proszę, kup nowy samochód, zamiast dodawać odkurzacz w swoim starym samochodzie. – colidyre

7

Jeśli używasz Python 2, nie zapomnij, aby dodać komentarz plik kodowania UTF-8 na pierwszej linii skryptu.

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

Naprawi to niektóre problemy z Unicode i ułatwi Ci życie.