天天看點

python學習:常用的 json 操作

你一定聽說過 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 對象,我們來觀察下它。

  1. 它是用 {} 括起來的一個集合,每一項都包含名稱 和值 ,如 name 就是名稱,而值就是 xxx。
  2. 名稱可以是任意字元串,但必須是字元串才可以哦。
  3. 值隻要是上面 6 種類型之一就可以
  4. 名稱/值 對沒有固定的順序,可以是任意順序
  5. 可以支援無限層的嵌套,如 obj 對象中嵌套了一個 address 對象,但是為了保證處理的高效性,請盡量保持結構的扁平性,也就是不要嵌套太多層哦)

為了能夠處理 JSON 資料,許多語言都有對應的資料類型可以映射為 JSON 對象,那麼 python 中是什麼資料類型呢?

是 dict

JSON 數組有哪些特點?

上面代碼中的 ​

​arr_simple ​

​​和​

​arr_complex​

​都表示數組,它們有哪些特點呢?

  1. 是一個 有序序列
  2. 隻有 值 組成
  3. 值可以是任意類型的 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 操作

有了這張表,我們就可以清楚的知道 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 操作

編碼對照表和解碼對照表并不是一一對應的,是以如果一個 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']      

6.結語