你一定聽說過 JSON 吧。JSON 是目前最常用的資料傳輸格式之一,純文字,容易使用,友善閱讀,最重要的是在多個場合都被大量被使用。
1.什麼是 JSON?
Json (Javascript Object Notation) 是一種輕量級的資料交換格式,它基于 Javascript 的對象字面量。盡管它隻是 Javascript 的一個子集,但它與語言無關。以現代程式設計語言編寫的程式,都可以用它來彼此交換資料。它是一種文本格式,人和機器都可以閱讀它。
—— 《Javascript 語言精粹》
既然以現代程式設計語言都可以用它來交換資料,強大的 python 當然也不例外。要更好的使用 JSON 一定要先了解下它的文法。
2.JSON 的文法
JSON 的值分為 6 種類型,分别是對象,數組,字元串,數字,布爾值 (true 和 false )和null。來看一個典型的 JSON 集合,體會下這些類型。
{
"obj": {
"name": "xxx",
"address": {
"country": "china",
"city": "TianJin"
}
},
"arr_simple": [1, 2, 3, 5],
"arr_complex": [
1,
"a",
{
"b": "yyy"
},
true,
null
],
"str": "I am a string",
"num": 888,
"booValue": false,
"nullValue": null
}
看上面代碼, JSON 文法有什麼特點呢?
- JSON 字元串必須使用 雙引号包圍
- 可以在任何值前後插入空白(包括空格,制表符,回車,換行),當然這些空白符也可以去除。
像字元串,數字,布爾值,null 都比較簡單,無需細數,接下來我們重點來看下對象和數組。
JSON 對象有哪些特點?
JSON 對象的結構是什麼樣子呢?
上面代碼中的 obj 就是一個 JSON 對象,我們來觀察下它。
- 它是用 {} 括起來的一個集合,每一項都包含名稱 和值 ,如 name 就是名稱,而值就是 xxx。
- 名稱可以是任意字元串,但必須是字元串才可以哦。
- 值隻要是上面 6 種類型之一就可以
- 名稱/值 對沒有固定的順序,可以是任意順序
- 可以支援無限層的嵌套,如 obj 對象中嵌套了一個 address 對象,但是為了保證處理的高效性,請盡量保持結構的扁平性,也就是不要嵌套太多層哦)
為了能夠處理 JSON 資料,許多語言都有對應的資料類型可以映射為 JSON 對象,那麼 python 中是什麼資料類型呢?
是 dict
JSON 數組有哪些特點?
上面代碼中的
arr_simple
和
arr_complex
都表示數組,它們有哪些特點呢?
- 是一個 有序序列
- 隻有 值 組成
- 值可以是任意類型的 JSON 值,如 arr_complex 數組。
python 也有能夠映射為 JSON 對象的資料類型,是 list 和 tuple
什麼是編碼和解碼?
說到 JSON 和 python 之間的轉換,就會涉及到兩個名詞:編碼 和 解碼。
那麼到底什麼是編碼和解碼呢?
編碼是資訊從一種形式或格式轉換為另一種形式的過程。解碼,是編碼的逆過程,亦即把編碼過的資訊恢複成原來樣式。
——維基百科
編碼的作用則是為了利于傳輸和存儲,JSON 當然是非常适合的。是以,
- 把 python 對象轉換成 JSON 的過程就稱為編碼
- 把 JSON 轉換成 python 對象的過程就稱為解碼
3.常用的 json 操作有哪些?
剛開始接觸 json 的操作,我主要有下面幾個疑問:
- json 操作需要什麼庫?
- 如何将 python 對象轉換成 JSON字元串,更進一步,能不能直接轉換成檔案句柄存儲到檔案中?(編碼)
- 如何将 json 字元串轉換成 python 對象,更進一步,能不能直接将 JSON 格式的檔案轉換成 python 對象?(解碼)
下面就讓我們一一來探索這些問題。
json 操作需要什麼庫?
使用 json 函數前需要先導入 json 庫:
import
json 庫本身就是 python 内置的标準庫,是以你不需要做任何安裝的操作。隻要聲明了上面語句,就可直接使用。
4.如何将 python 編碼成 JSON?
python 編碼為 JSON 的對照表
要完成這個功能,先要看下 python 資料結構編碼為 json 的對照表。

有了這張表,我們就可以清楚的知道 python 對象将編碼成的 json 格式。
json.dumps()
json.dumps() 方法的作用就是将 python 對象轉換成 JSON 字元串,下面來看具體的函數聲明:
json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)
參數看起來好多啊,不過不用擔心,這麼多參數,隻有第一個參數是必填的。下面就來一一了解下這些參數的意義
- obj 就是要編碼的 python 對象
- skipkeys 預設值是 False。設定為 True ,假如 obj 中的 dict keys 不是基本類型(str , int , float , bool , None ), 就會被忽略,而不是抛出 TypeError 錯誤
-
ensure_ascii 預設是 True , 表示預設使用ascii 編碼。如果 obj 内含有非 ASCII 字元,就會出現 “\uXXXX” 格式顯式的資料, 設定成 False 就會使用字元本來的編碼。
這裡要注意,如果輸入是中文,需要指定 ensure_ascii=False
- check_circular 預設值是 True,如果設定為 False 就不會檢查内部類型是否包含循環引用,而且循環引用會導緻 OverflowError
-
allow_nan 預設值為 False ,如果碰到超過範圍的 float 值(nan, inf, -inf )就使用 (NaN,Infinity, -Infinity) 替換
如果為 True 碰到這些值則會導緻 ValueError
-
indent 縮進設定
如果是非負整數或者 string, JSON Array 元素和對象元素将會按照設定的縮進格式化顯示
值為 0, 負值,或者 “” 隻會插入新的一行
值為 None (也是預設值)會盡可能的壓縮
-
separators 分隔符。
如果要設定它,參數需要是一個元組(item_separator, key_separator)
預設值是 (', ', ': ') ,表示 keys 之間用 , 隔開,而 key 和 value 之間用 : 隔開
- sort_keys 預設值是 False ,如果設定成 True , dict 結構的輸出就會按照 key 來排序
- encoding 預設值是 UTF-8 用于設定 JSON 資料的編碼方式,在進行中文時這裡一定要注意。
來看一個例子
>>> import json
>>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>> print(json.dumps("\"foo\bar"))
"\"foo\bar"
>>> print(json.dumps('\u1234'))
"\u1234"
>>> print(json.dumps('\\'))
"\\"
>>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
{"a": 0, "b": 0, "c": 0}
json.dump()
json.dump() 函數的作用就是将 python 對象轉換成 JSON 字元串,并将其通過 fp 檔案流寫入到檔案中。來看下具體的函數聲明:
.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
和前面的 dumps 函數進行比較,會發現兩個函數的參數是非常相似的,而且它們的意義也都相同。來看下面的例子
>>> import json
>>> from io import StringIO
>>> io = StringIO()
>>> json.dump(['streaming API'], io)
>>> io.getvalue()
'["streaming API"]'
5.如何将 JSON 解碼成 python 對象?
JSON 解碼為 python 的對照表
要完成這個功能,也先要看下 json 解碼為 python 對象的對照表
編碼對照表和解碼對照表并不是一一對應的,是以如果一個 python對象 先編碼成 JSON,再轉碼回來後得到的對象可就不一定完全相等了。
json.loads()
這個方法的作用就是将參數 s 按照上面的對照表反序列化為一個 python 對象。參數 s 可以是 str ,byte 或者byteArray 格式, 但必須要包含 JSON 文本才可以)。
具體函數聲明如下:
json.loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
下面就來一一了解下一些常用參數的意義
- s 就是要解碼的 python 字元串
- encoding 指定編碼格式
- parse_float ,預設情況下相當于 float(num_str)。如果設定為其他值,将會把一個 JSON 字元串按照 float 解碼調用,
- parse_int ,預設情況下相當于 int(num_str),如果指定,将把每個 JSON 字元串按照 int 解碼調用
來看下面的例子,其中最後一行就指定了 parse_float 。
'''
學習中遇到問題沒人解答?小編建立了一個Python學習交流群:711312441
尋找有志同道合的小夥伴,互幫互助,群裡還有不錯的視訊學習教程和PDF電子書!
'''
>>> import json
>>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
['foo', {'bar': ['baz', None, 1.0, 2]}]
>>> json.loads('"\\"foo\\bar"')
'"foo\x08ar'
>>> import decimal
>>> json.loads('1.1', parse_float=decimal.Decimal)
Decimal('1.1')
json.load()
先來看函數聲明
.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
>>> import json
>>> from io import StringIO
>>> io = StringIO('["streaming API"]')
>>> json.load(io)
['streaming API']