前言
養成一個好的習慣只需要堅持21天,Day14
什是JSON?
JSON是輕量級的文本數據交換格式,指的是 JavaScript 對象表示法(JavaScript Object Notation),類似XML但又比 XML 更小、更快,更易解析。
JSON語法
JSON數據的書寫格式是:"名稱":“值”
,例如:
"name":"湯姆"
JSON的值可以是:數字、字符串、邏輯值、數組、對象和null。
{"age":30}
{"name":"湯姆","country":"England"}
{"flag":true}
{"money":null}
JSON數組:
{
"sites": [
{ "name":"湯姆" , "country":"England "},
{ "name":"張三" , "country“:”China" },
{ "name":"里斯" , "country":"France" }
]
}
JSON與Python對象
在Python的內部有json模塊,提供了Python對象到JSON格式的轉換。
把Python對象編程一個JSON:
>>> import json
>>> d = dict(name='Bob',age=20,score=90)
>>> json.dumps(d)
# '{"name": "Bob", "age": 20, "score": 90}'
json.dumps()
方法返回一個str
,內容是標準的JSON。類似的,dump()
方法可以直接把JSON寫入一個file-like Object
,file-like Object
是像open()
函數返回的這種有個read()
方法的對象,除了file外,還可以是內存的字節流,網絡流,自定義流等等。
把JSON反序列化爲Python對象:
>>> json_str = '{"name": "Bob", "age": 20, "score": 90}'
>>> json.loads(json_str)
# {'name': 'Bob', 'age': 20, 'score': 90}
json.loads()
函數把JSON的字符串反序列化,json.load()
函數從file-like Object
中讀取字符串並反序列化。
JSON進階
Python的dict
對象可以直接序列化爲JSON的{}
,對於我們使用class表示對象時,我們不能直接對類的實例進行序列化,會出現TypeError
錯誤:
import json
class Student(object):
def __init__(self,name,age,score):
self.name = name
self.age = age
self.score = score
s = Studrnt('Bob',20,90)
print(json.dumps(s))
# Traceback (most recent call last):
...
# TypeError: <__main__.Student object at 0x10603cc50> is not JSON serializable
json模塊中的dumps()
方法還提供了許多可選參數,可選參數default
就是把任意一個對象變成一個可序列爲JSON
的對象,我們只需要爲Student
專門寫一個轉換函數,再把函數傳進去即可:
def student2dict(std):
return {
'name': std.name,
'age': std.age,
'score': std.score
接下來運行:
>>> print(json.dumps(s, default=student2dict))
# {"age": 20, "name": "Bob", "score": 88}
Student
實例s
首先被student2dict()
函數轉換成dict,然後再被順利序列化爲JSON。
如果換一個類,比如Teacher類,我們就無法再用此方法進行轉化,每次都編寫一個轉換函數太麻煩了。
通常class的實例都有一個__dict__
屬性,它就是一個__dict__
,用來存儲實例變量。也有少數例外,定義了__slots__
的class就沒有__dict__
屬性。
print(json.dumps(s, default=lambda obj: obj.__dict__))
練習
對中文進行JSON序列化時,json.dumps()
提供了一個ensure_ascii
參數,觀察該參數對結果的影響:
>>> obj = dict(name='小明', age=20)
>>> s = json.dumps(obj, ensure_ascii=True)
>>> s
# '{"name": "\\u5c0f\\u660e", "age": 20}'
>>> obj = dict(name='小明', age=20)
>>> s = json.dumps(obj, ensure_ascii=False)
>>> s
# '{"name": "小明", "age": 20}'
由上面的運行結果可知,想輸出真正的中文需要指定ensure_ascii=False
,這是因爲json.dumps()
序列化時對中文默認使用的ascii編碼。