แปลงพจนานุกรม Python เป็นอาร์เรย์ JSON


100

ขณะนี้ฉันมีพจนานุกรมนี้พิมพ์โดยใช้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}

เมื่อฉันทำสิ่งนี้:

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

ฉันได้รับข้อผิดพลาดนี้: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte


ปัญหาของคุณอยู่ที่นี่:\xff
Benjamin Toueg

คำตอบ:


168

หากคุณสบายดีกับสัญลักษณ์ที่ไม่สามารถพิมพ์ได้ใน json ของคุณให้เพิ่มensure_ascii=Falseในการdumpsโทร

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

ถ้าensure_asciiเป็นเท็จแล้วค่าตอบแทนจะเป็น unicodeเรื่องเช่นหลามปกติstrเพื่อunicode กฎบังคับแทนการหนีไปยัง strASCII


1
เพิ่มindent=nตัวเลือกในการพิมพ์แบบสวยnจำนวนช่องว่างที่จะเยื้อง
RTF

17

sure_ascii = False จริง ๆ เท่านั้นที่จะเลื่อนปัญหาไปสู่ขั้นตอนการถอดรหัส:

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

ท้ายที่สุดแล้วคุณไม่สามารถจัดเก็บไบต์ดิบในเอกสาร JSON ได้ดังนั้นคุณจะต้องใช้วิธีการบางอย่างในการเข้ารหัสลำดับไบต์ตามอำเภอใจเป็นสตริง ASCII เช่น 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'}

คุณสามารถส่งผ่านข้อมูลไบนารีโดยพลการ (ไม่มีประสิทธิภาพ) ใน json โดยใช้การเข้ารหัส 'latin1'
jfs

1
คุณทำได้ฉันคิดว่า แต่ json ได้รับการออกแบบ / ตั้งใจให้ใช้ utf-8
Karl Knechtel

2
@JFSebastian: อันที่จริงไม่มีประสิทธิภาพมากเมื่อเทียบกับb64encode. ตัวอย่างเช่นสำหรับสตริง 256 ตัวอักษรs = ''.join(chr(i) for i in xrange(256)), VSlen(json.dumps(b64encode(s))) == 346 len(json.dumps(s.decode('latin1'))) == 1045
martineau

10

หากคุณใช้ Python 2 อย่าลืมเพิ่มความคิดเห็นการเข้ารหัสไฟล์ UTF-8 ในบรรทัดแรกของสคริปต์ของคุณ

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

วิธีนี้จะแก้ไขปัญหา Unicode และทำให้ชีวิตของคุณง่ายขึ้น


2

ทางออกที่เป็นไปได้อย่างหนึ่งที่ฉันใช้คือการใช้ python3 ดูเหมือนว่าจะแก้ปัญหา utf ได้หลายอย่าง

ขออภัยสำหรับคำตอบที่ล่าช้า แต่อาจช่วยผู้คนได้ในอนาคต

ตัวอย่างเช่น,

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

4
แน่นอนว่าคุณพูดถูก Python 3 แก้ไขปัญหาการเข้ารหัสหลายอย่าง แต่นั่นไม่ใช่คำตอบสำหรับคำถามนั้น มีการติดแท็กอย่างชัดเจนด้วย python-2.7 สิ่งที่คุณกำลังพูดก็เป็นดังนี้: ไม่มีเครื่องดูดฝุ่นในตัวในรถคันเก่าของคุณ ดังนั้นโปรดซื้อรถใหม่แทนการเพิ่มเครื่องดูดฝุ่นในรถคันเก่าของคุณ
colidyre
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.