Python3的Json模塊詳解

簡介

Json模塊主要用來進行Python對象的序列化和反序列化。
該模塊中經常使用的方法有如下四個:python

  • json.dump
    將Python對象序列化爲Json格式的數據流並寫入文件類型的對象中json

  • json.dumps
    將Python對象序列化爲Json格式的字符串數組

  • json.load
    從文件類型的對象中讀取Json格式的數據並反序列化成Python對象ide

  • json.loads
    將包含Json格式數據的字符串反序列化成Python對象函數

進行序列化時,Python類型與Json類型的轉換關係以下表所示:this

Python JSON
dict object
list, tuple array
str string
int, float number
True true
False false
None null

進行反序列化時,Json類型與Python類型的轉換關係以下:編碼

JSON Python
object dict
array list
string str
number(int) int
number(real) float
true True
false False
null None

經常使用方法詳解

因爲 json.dumpjson.dumps這兩個方法、的做用與使用方法相似,故只對其中之一詳細介紹。
一樣地,json.loadjson.loads這兩個方法的做用與使用方法相似,故也只對其中之一詳細介紹。spa

json.dumps

該方法包含一個位置參數和多個僅限關鍵字參數,分別以下所示:.net

  • obj
    要序列化的Python對象code

  • skipkeys=False
    是否跳過要序列化的對象中字典元素的key不是基本類型的數據;
    若是爲True,則跳過,若是爲False,將拋出TypeError異常。

    >>> emp_info = {'name': 'bob', b'age': 24}  # 包含key爲bytes類型的元素
    >>> json.dumps(emp_info)  # skipkeys參數爲默認值False
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 231, in dumps
        return _default_encoder.encode(obj)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
        chunks = self.iterencode(o, _one_shot=True)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
        return _iterencode(o, 0)
    TypeError: keys must be str, int, float, bool or None, not bytes
    >>> json.dumps(emp_info, skipkeys=True)  # skipkeys參數設置爲True時則可成功序列化
    '{"name": "bob"}'
  • ensure_ascii=True
    是否將要序列化的對象中的字符串中的非ascii字符進行轉義。
    若是該參數爲True,則將字符串中的非ascii字符轉義成unicode字符串,不然,將不會進行轉義。

    >>> message = '我愛Python3'
    >>> json.dumps(message)  # ensure_ascii參數默認值爲True,將會把非ascii字符轉移成unicode字符串
    '"\\u6211\\u7231Python3"'
    >>> json.dumps(message, ensure_ascii=False)  # ensure_ascii參數設置爲False時,不會進行轉義
    '"我愛Python3"'
  • check_circular=True
    是否進行容器類型的循環引用檢查。
    若是該參數設置爲False,則不進行檢查,可是可能會引起OverflowError或更嚴重的狀況。
    若是該參數設置爲True,則將進行容器類型的循環引用檢查,並在發現循環引用時拋出異常。

    emp_dict = {'id': 1, 'dept': 'sales'}
    >>> emp_dict['info'] = emp_dict  # 字典中包含循環引用
    >>> json.dumps(emp_dict)  # 默認進行循環引用的檢查,將引起ValueError異常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 231, in dumps
        return _default_encoder.encode(obj)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
        chunks = self.iterencode(o, _one_shot=True)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
        return _iterencode(o, 0)
    ValueError: Circular reference detected
    >>> json.dumps(emp_dict, check_circular=False)  # 設置爲不進行循環引用的檢查,可是在編碼Json對象時仍然引起了異常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 238, in dumps
      **kw).encode(obj)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
        chunks = self.iterencode(o, _one_shot=True)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
        return _iterencode(o, 0)
    RecursionError: maximum recursion depth exceeded while encoding a JSON object
  • allow_nan=True
    是否容許序列化超出範圍的float類型的值(如float(‘inf’)、float(’-inf’)、float(‘nan’))。
    若是該參數設置爲True,則上面列出的那些值將依次使用JavaScript中等價的值(Infinity、-Infinity、NaN)來進 行替代;
    若是該參數設置爲False,而且要序列化的對象中出現了那些超出範圍的值,則將引起ValueError異常。

    >>> num_list = [2, 5, float('inf'), float('-inf'), float('nan')]
    >>> json.dumps(num_list)  # allow_nan的值默認爲True,列表中後三個值將被替換爲js中等價的值
    '[2, 5, Infinity, -Infinity, NaN]'
    >>> json.dumps(num_list, allow_nan=False)  # allow_nan設置爲False,引起ValueError異常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 238, in dumps
      **kw).encode(obj)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
        chunks = self.iterencode(o, _one_shot=True)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
        return _iterencode(o, 0)
    ValueError: Out of range float values are not JSON compliant
  • indent=None
    是否在數組元素和對象成員前增長縮進以便使格式更加美觀。
    若是該參數設置爲大於等於1的整數,則添加換行符和對應數量的空格表示縮進,若是設置爲0,則表示只添加換行符,若是設置爲None,則表示無縮進。

    >>> response = {'status': 'success', 'code': 200, 'data': ['002', 'json', 5000]}
    >>> print(json.dumps(response))  # 默認值None,不縮進
    {"status": "success", "code": 200, "data": ["002", "json", 5000]}
    >>> print(json.dumps(response, indent=0))  # 設置爲0,則只添加換行
    {
    "status": "success",
    "code": 200,
    "data": [
    "002",
    "json",
    5000
    ]
    }
    >>> print(json.dumps(response, indent=4))  # 設置爲4,添加換行和縮進
    {
        "status": "success",
        "code": 200,
        "data": [
            "002",
            "json",
            5000
        ]
    }
  • separators=None
    設置Json中各項之間、對象的鍵和值之間的分隔符;
    該參數必須是一個2元組,元組第一個元素表示Json數據中各項之間的分隔符,元組的第二個元素表示Json對象的鍵和值之間的分隔符。默認的分隔符爲(’,’, ‘:’)

    >>> response = {'status': 'success', 'code': 200, 'data': ['002', 'json', 5000]}
    >>> print(json.dumps(response, separators=(';', '!')))
    >>> print(json.dumps(response, indent = 4, separators=(';', '!')))
    {
        "status"!"success";
        "code"!200;
        "data"![
            "002";
            "json";
            5000
        ]
    }
  • default=None
    指定一個函數,用來將不可進行序列化的Python對象轉化爲可序列化的Python對象

    >>> json.dumps(b'hello world')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 231, in dumps
        return _default_encoder.encode(obj)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
        chunks = self.iterencode(o, _one_shot=True)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
        return _iterencode(o, 0)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default
        raise TypeError(f'Object of type {o.__class__.__name__} '
    TypeError: Object of type bytes is not JSON serializable
    >>> json.dumps(b'hello world', default=list)
    '[104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]'
    >>> json.dumps(b'hello world', default=str)
    '"b\'hello world\'"'
  • sort_keys=False
    是否要將對象中字典元素按照key進行排序。
    默認爲False,即不進行排序,若指定爲True,則會進行排序。

    >>> emp_info = {'name': 'bob', 'age': 23, 'dept': 'sales', 'gender': 'male'}
    >>> print(json.dumps(emp_info, indent = 4))  # 不按照key排序
    {
        "name": "bob",
        "age": 23,
        "dept": "sales",
        "gender": "male"
    }
    >>> print(json.dumps(emp_info, indent = 4, sort_keys=True))  # 按照key進行排序
    {
        "age": 23,
        "dept": "sales",
        "gender": "male",
        "name": "bob"
    }
  • cls=None
    指定一個定製的JSONEncoder的子類(例如,重寫了.default()方法用來序列化附加的類型),指定該參數時請使用cls關鍵字參數。若是未指定該參數,則將使用默認的JSONEncoder。

    >>> class IteratorEncoder(json.encoder.JSONEncoder):
    ...     def default(self, o):
    ...         try:
    ...             iterable = iter(o)
    ...         except TypeError:
    ...             pass
    ...         else:
    ...             return list(iterable)
    ...         return super().default(self, o)
    ... 
    >>> def get_nums(n):
    ...     if not isinstance(n, int):
    ...         raise TypeError('Expected int object')
    ...     while n > 0:
    ...         yield n
    ...         n -= 1
    ... 
    >>> print(json.dumps(get_nums(10), indent=4, cls=IteratorEncoder))
    [
        10,
        9,
        8,
        7,
        6,
        5,
        4,
        3,
        2,
        1
    ]

json.dump

下面演示下該方法的簡單用法:

>>> response = {'status': 'success', 'code': 200, 'data': {'username': 'bob', 'user_level': 6, 'nickname': 'playboy'}}
>>> with open('res.json', 'w', encoding='utf-8') as f:
...     json.dump(response, f, indent=4)
... 
>>> os.system('cat res.json')
{
    "status": "success",
    "code": 200,
    "data": {
        "username": "bob",
        "user_level": 6,
        "nickname": "playboy"
    }
}0
>>>

json.loads

該方法包含一個位置參數和多個僅限關鍵字參數,分別以下所示:

  • s

  • encoding=None
    該參數已棄用,將會被忽略

  • cls=None
    指定一個定製的JsonDecoder子類,以便實現特定的反序列化需求;

  • object_hook=None
    接受一個可調用對象,用於處理解碼後生成的Python對象中dict類型的值。
    注意,這個處理過程是遞歸進行的,即返回的Python對象內部全部的字典結構都將被這個方法處理

    >>> emp_info = {'name': 'bob', 'age': 25, 'gender': 'Male'}
    >>> def obj_hook(_dict):
    ...     return list(_dict.items())
    ... 
    >>> json.loads(json.dumps(emp_info))
    {'name': 'bob', 'age': 25, 'gender': 'Male'}
    >>> json.loads(json.dumps(emp_info), object_hook=obj_hook)
    [('name', 'bob'), ('age', 25), ('gender', 'Male')]
    >>> emp_list = [25, emp_info]
    >>> emp_list
    [25, {'name': 'bob', 'age': 25, 'gender': 'Male'}]
    >>> json.loads(json.dumps(emp_list),object_hook=obj_hook)
    [25, [('name', 'bob'), ('age', 25), ('gender', 'Male')]]
    >>> emp_d = [25, {'name': 'bob', 'age': 25, 'gender': 'Male', 'emp_info': {'count': 9,   'total_salary': 120000}}]
    >>> json.loads(json.dumps(emp_d),object_hook=obj_hook)
    [25, [('name', 'bob'), ('age', 25), ('gender', 'Male'), ('emp_info', [('count', 9), ('total_salary', 120000)])]]
  • parse_float=None
    用於處理解碼後的Python對象中的float類型的值。

    >>> json.loads('[23.5, 43.32, 5.934]', parse_float=lambda x: int(x))  # 將解碼後的全部的float類型的值轉成int類型
    [23, 43, 5]
    >>> json.loads('[23.5, 43.32, 5.934]', parse_float=lambda x: str(x))  # 將解碼後的全部的float類型的值轉成str類型
    ['23.5', '43.32', '5.934']
  • parse_constant=None
    接受一個可調用對象,用於解碼時對Infinity、-Infinity、NaN或其餘非法的Json數值的處理。

    >>> def parse_cons(cons):
    ...     if cons == 'Infinity':
    ...         return 100000000
    ...     elif cons == '-Infinity':
    ...         return -100000000
    ...     elif cons == 'NaN':
    ...         return None
    ...     else:
    ...         raise Value(f"Can't convert this value {cons}")
    ... 
    >>> json.loads('[Infinity, -Infinity, NaN]', parse_constant=parse_cons)
    [100000000, -100000000, None]
  • object_parse_hook=None
    若是指定了該參數而且設置爲一個可調用對象,那麼Json對象將被解碼成一個元素爲二元組的列表,二元組的兩個元素分別爲Json對象中的鍵值對的鍵和值,而且列表中元素的順序與Json對象中鍵值對的順序一致。

>>> emp_info = {'name': 'bob', 'age': 23, 'dept': 'sales', 'gender': 'male'}
>>> json.loads(json.dumps(emp_info), object_pairs_hook=str)
"[('name', 'bob'), ('age', 23), ('dept', 'sales'), ('gender', 'male')]"
>>> from collections import OrderedDict
>>> json.loads(json.dumps(emp_info), object_pairs_hook=OrderedDict)
OrderedDict([('name', 'bob'), ('age', 23), ('dept', 'sales'), ('gender', 'male')])

json.load

下面演示下該方法的簡單用法:

>>> with open('res.json', encoding='utf-8') as f:
...     json.load(f)
... 
{'status': 'success', 'code': 200, 'data': {'username': 'bob', 'user_level': 6, 'nickname': 'playboy'}}

轉載:https://blog.csdn.net/swinfans/article/details/86501555

相關文章
相關標籤/搜索