Ubah kamus Python menjadi larik JSON

98

Saat ini saya memiliki kamus ini, yang dicetak menggunakan 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}

Ketika saya melakukan ini:

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

Saya mendapatkan kesalahan ini: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

HyperDevil
sumber
Masalah Anda terletak di sini:\xff
Benjamin Toueg

Jawaban:

167

Jika Anda baik-baik saja dengan simbol yang tidak dapat dicetak di json Anda, tambahkan ensure_ascii=Falseke dumpspanggilan.

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

Jika ensure_asciisalah, maka nilai yang dikembalikan akan menjadi unicodeinstance yang tunduk pada Python normal strterhadap unicode aturan pemaksaan alih-alih di-escape ke ASCII str.

kmerenkov
sumber
1
tambahkan indent=nke opsi untuk cukup mencetak, di mana nadalah jumlah spasi untuk indentasi
RTF
17

sure_ascii = False benar-benar hanya mengalihkan masalah ke tahap decoding:

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

Pada akhirnya, Anda tidak dapat menyimpan byte mentah dalam dokumen JSON, jadi Anda akan ingin menggunakan beberapa cara untuk mengenkode urutan byte arbitrer secara jelas sebagai string ASCII - seperti 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
sumber
Anda dapat meneruskan data biner sewenang-wenang (tidak efisien) di json menggunakan pengkodean 'latin1'
jfs
1
Anda bisa, saya kira, tetapi json dirancang / dimaksudkan untuk menggunakan utf-8.
Karl Knechtel
2
@JFSebastian: Memang, sangat tidak efisien dibandingkan dengan b64encode. Misalnya, untuk string 256 karakter s = ''.join(chr(i) for i in xrange(256)), len(json.dumps(b64encode(s))) == 346vs len(json.dumps(s.decode('latin1'))) == 1045.
martineau
10

Jika Anda menggunakan Python 2, jangan lupa untuk menambahkan komentar encoding file UTF-8 di baris pertama skrip Anda.

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

Ini akan memperbaiki beberapa masalah Unicode dan membuat hidup Anda lebih mudah.

keadilan
sumber
2

Salah satu solusi yang mungkin saya gunakan adalah dengan menggunakan python3. Tampaknya menyelesaikan banyak masalah utf.

Maaf atas jawaban yang terlambat, tetapi ini dapat membantu orang di masa depan.

Sebagai contoh,

#!/usr/bin/env python3
import json
# your code follows
Ralph Yozzo
sumber
4
Tentu, Anda benar sekali, Python 3 memecahkan banyak masalah encoding. Tapi itu bukanlah jawaban untuk pertanyaan itu. Ini secara eksplisit ditandai dengan python-2.7. Jadi yang Anda katakan adalah sesuatu seperti ini: Tidak ada penyedot debu built-in di mobil lama Anda. Jadi tolong beli mobil baru daripada menambahkan penyedot debu di mobil lama Anda.
colidyre