json --- JSON 編碼和解碼器?

源代碼: Lib/json/__init__.py


JSON (JavaScript Object Notation),由 RFC 7159 (它取代了 RFC 4627) 和 ECMA-404 指定,是一個受 JavaScript 的對象字面值句法啟發的輕量級數據交換格式,盡管它不僅僅是一個嚴格意義上的 JavaScript 的子集 1

json 提供了與標準庫 marshalpickle 相似的API接口。

對基本的 Python 對象層次結構進行編碼:

>>> 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}
>>> from io import StringIO
>>> io = StringIO()
>>> json.dump(['streaming API'], io)
>>> io.getvalue()
'["streaming API"]'

緊湊編碼:

>>> import json
>>> json.dumps([1, 2, 3, {'4': 5, '6': 7}], separators=(',', ':'))
'[1,2,3,{"4":5,"6":7}]'

美化輸出:

>>> import json
>>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4))
{
    "4": 5,
    "6": 7
}

JSON解碼:

>>> import json
>>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
['foo', {'bar': ['baz', None, 1.0, 2]}]
>>> json.loads('"\\"foo\\bar"')
'"foo\x08ar'
>>> from io import StringIO
>>> io = StringIO('["streaming API"]')
>>> json.load(io)
['streaming API']

特殊 JSON 對象解碼:

>>> import json
>>> def as_complex(dct):
...     if '__complex__' in dct:
...         return complex(dct['real'], dct['imag'])
...     return dct
...
>>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
...     object_hook=as_complex)
(1+2j)
>>> import decimal
>>> json.loads('1.1', parse_float=decimal.Decimal)
Decimal('1.1')

擴展 JSONEncoder

>>> import json
>>> class ComplexEncoder(json.JSONEncoder):
...     def default(self, obj):
...         if isinstance(obj, complex):
...             return [obj.real, obj.imag]
...         # Let the base class default method raise the TypeError
...         return json.JSONEncoder.default(self, obj)
...
>>> json.dumps(2 + 1j, cls=ComplexEncoder)
'[2.0, 1.0]'
>>> ComplexEncoder().encode(2 + 1j)
'[2.0, 1.0]'
>>> list(ComplexEncoder().iterencode(2 + 1j))
['[2.0', ', 1.0', ']']

從命令行使用 json.tool 來驗證并美化輸出:

$ echo '{"json":"obj"}' | python -m json.tool
{
    "json": "obj"
}
$ echo '{1.2:3.4}' | python -m json.tool
Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

詳細文檔請參見 命令行界面

注解

JSON 是 YAML 1.2 的一個子集。由該模塊的默認設置生成的 JSON (尤其是默認的 “分隔符” 設置值)也是 YAML 1.0 and 1.1 的一個子集。因此該模塊也能夠用于序列化為 YAML。

基本使用?

json.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)?

使用這個 轉換表obj 序列化為 JSON 格式化流形式的 fp (支持 .write()file-like object)。

如果 skipkeys 是 true (默認為 False),那么那些不是基本對象(包括 str, intfloatboolNone)的字典的鍵會被跳過;否則引發一個 TypeError

json 模塊始終產生 str 對象而非 bytes 對象。因此,fp.write() 必須支持 str 輸入。

如果 ensure_ascii 是 true (即默認值),輸出保證將所有輸入的非 ASCII 字符轉義。如果 ensure_ascii 是 false,這些字符會原樣輸出。

如果 check_circular 是為假值 (默認為 True),那么容器類型的循環引用檢驗會被跳過并且循環引用會引發一個 OverflowError (或者更糟的情況)。

如果 allow_nan 是 false(默認為 True),那么在對嚴格 JSON 規格范圍外的 float 類型值(naninf-inf)進行序列化時會引發一個 ValueError。如果 allow_nan 是 true,則使用它們的 JavaScript 等價形式(NaNInfinity-Infinity)。

如果 indent 是一個非負整數或者字符串,那么 JSON 數組元素和對象成員會被美化輸出為該值指定的縮進等級。 如果縮進等級為零、負數或者 "",則只會添加換行符。 None (默認值) 選擇最緊湊的表達。 使用一個正整數會讓每一層縮進同樣數量的空格。 如果 indent 是一個字符串 (比如 "\t"),那個字符串會被用于縮進每一層。

在 3.2 版更改: 現允許使用字符串作為 indent 而不再僅僅是整數。

當被指定時,separators 應當是一個 (item_separator, key_separator) 元組。當 indentNone 時,默認值取 (', ', ': '),否則取 (',', ': ')。為了得到最緊湊的 JSON 表達式,你應該指定其為 (',', ':') 以消除空白字符。

在 3.4 版更改: 現當 indent 不是 None 時,采用 (',', ': ') 作為默認值。

default 被指定時,其應該是一個函數,每當某個對象無法被序列化時它會被調用。它應該返回該對象的一個可以被 JSON 編碼的版本或者引發一個 TypeError。如果沒有被指定,則會直接引發 TypeError

如果 sort_keys 是 true(默認為 False),那么字典的輸出會以鍵的順序排序。

為了使用一個自定義的 JSONEncoder 子類(比如:覆蓋了 default() 方法來序列化額外的類型), 通過 cls 關鍵字參數來指定;否則將使用 JSONEncoder

在 3.6 版更改: 所有可選形參現在都是 僅限關鍵字參數

注解

picklemarshal 不同,JSON 不是一個具有框架的協議,所以嘗試多次使用同一個 fp 調用 dump() 來序列化多個對象會產生一個不合規的 JSON 文件。

json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)?

使用這個 轉換表obj 序列化為 JSON 格式的 str。 其參數的含義與 dump() 中的相同。

注解

JSON 中的鍵-值對中的鍵永遠是 str 類型的。當一個對象被轉化為 JSON 時,字典中所有的鍵都會被強制轉換為字符串。這所造成的結果是字典被轉換為 JSON 然后轉換回字典時可能和原來的不相等。換句話說,如果 x 具有非字符串的鍵,則有 loads(dumps(x)) != x

json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)?

使用這個 轉換表fp (一個支持 .read() 并包含一個 JSON 文檔的 text file 或者 binary file) 反序列化為一個 Python 對象。

object_hook 是一個可選的函數,它會被調用于每一個解碼出的對象字面量(即一個 dict)。object_hook 的返回值會取代原本的 dict。這一特性能夠被用于實現自定義解碼器(如 JSON-RPC 的類型提示)。

object_pairs_hook 是一個可選的函數,它會被調用于每一個有序列表對解碼出的對象字面量。 object_pairs_hook 的返回值將會取代原本的 dict 。這一特性能夠被用于實現自定義解碼器。如果 object_hook 也被定義, object_pairs_hook 優先。

在 3.1 版更改: 添加了對 object_pairs_hook 的支持。

parse_float ,如果指定,將與每個要解碼 JSON 浮點數一同調用。默認狀態下,相當于 float(num_str) 。可以用于對 JSON 浮點數使用其它數據類型和解析器 (比如 decimal.Decimal )。

parse_int ,如果指定,將與每個要解碼 JSON 整數的字符串一同調用。默認狀態下,相當于 int(num_str) 。可以用于對 JSON 整數使用其它數據類型和語法分析程序 (比如 float )。

parse_constant ,如果指定,將要與以下字符串中的一個一同調用: '-Infinity''Infinity''NaN' 。如果遇到無效的 JSON 數字它會被用于拋出異常。

在 3.1 版更改: parse_constant 不再調用 'null' , 'true' , 'false' 。

要使用自定義的 JSONDecoder 子類,用 cls 指定他;否則使用 JSONDecoder 。額外的關鍵詞參數會通過類的構造函數傳遞。

如果反序列化的數據不是有效 JSON 文檔,拋出 JSONDecodeError 錯誤。

在 3.6 版更改: 所有可選形參現在都是 僅限關鍵字參數

在 3.6 版更改: fp 現在可以是 binary file 。輸入編碼應當是 UTF-8 , UTF-16 或者 UTF-32 。

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 (一個包含 JSON 文檔的 str, bytesbytearray 實例) 反序列化為 Python 對象。

其他參數與在 load() 中的含義相同,只有 encoding 被忽略和棄用。

如果反序列化的數據不是有效 JSON 文檔,拋出 JSONDecodeError 錯誤。

在 3.6 版更改: s 現在可以為 bytesbytearray 類型。 輸入編碼應為 UTF-8, UTF-16 或 UTF-32。

編碼器和解碼器?

class json.JSONDecoder(*, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None)?

簡單的JSON解碼器。

默認情況下,解碼執行以下翻譯:

JSON

Python

object

dict

array

list

string

str

number (int)

int

number (real)

float

true

True

false

False

null

None

它還將“NaN”、“Infinity”和“-Infinity”理解為它們對應的“float”值,這超出了JSON規范。

object_hook ,如果指定,會被每個解碼的 JSON 對象的結果調用,并且返回值會替代給定 dict 。它可被用于提供自定義反序列化(比如去支持 JSON-RPC 類的暗示)。

如果指定了 object_pairs_hook 則它將被調用并傳入以對照值有序列表進行解碼的每個 JSON 對象的結果。 object_pairs_hook 的結果值將被用來替代 dict。 這一特性可被用于實現自定義解碼器。 如果還定義了 object_hook,則 object_pairs_hook 的優先級更高。

在 3.1 版更改: 添加了對 object_pairs_hook 的支持。

parse_float ,如果指定,將與每個要解碼 JSON 浮點數一同調用。默認狀態下,相當于 float(num_str) 。可以用于對 JSON 浮點數使用其它數據類型和解析器 (比如 decimal.Decimal )。

parse_int ,如果指定,將與每個要解碼 JSON 整數的字符串一同調用。默認狀態下,相當于 int(num_str) 。可以用于對 JSON 整數使用其它數據類型和語法分析程序 (比如 float )。

parse_constant ,如果指定,將要與以下字符串中的一個一同調用: '-Infinity''Infinity''NaN' 。如果遇到無效的 JSON 數字它會被用于拋出異常。

如果 strict 為 false (默認為 True ),那么控制字符將被允許在字符串內。在此上下文中的控制字符是那些編碼于范圍 0 -- 31 的字符,包括 '\t' (制表符), '\n''\0'

如果反序列化的數據不是有效 JSON 文檔,拋出 JSONDecodeError 錯誤。

在 3.6 版更改: 所有形參現在都是 僅限關鍵字參數

decode(s)?

返回 s 的 Python 表示形式(包含一個 JSON 文檔的 str 實例)。

如果給定的 JSON 文檔無效則將引發 JSONDecodeError

raw_decode(s)?

s 中解碼出 JSON 文檔(以 JSON 文檔開頭的一個 str 對象)并返回一個 Python 表示形式為 2 元組以及指明該文檔在 s 中結束位置的序號。

這可以用于從一個字符串解碼JSON文檔,該字符串的末尾可能有無關的數據。

class json.JSONEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)?

用于Python數據結構的可擴展JSON編碼器。

默認支持以下對象和類型:

Python

JSON

dict

object

list, tuple

array

str

string

int, float, int 和 float 派生的枚舉

number

True

true

False

false

None

null

在 3.4 版更改: 添加了對 int 和 float 派生的枚舉類的支持

為了將其拓展至識別其他對象,需要子類化并實現 default() 方法于另一種返回 o 的可序列化對象的方法如果可行,否則它應該調用超類實現(來引發 TypeError )。

如果 skipkeys 為假值(默認),則嘗試對不是 str, int, floatNone 的鍵進行編碼將會引發 TypeError。 如果 skipkeys 為真值,這些條目將被直接跳過。

如果 ensure_ascii 是 true (即默認值),輸出保證將所有輸入的非 ASCII 字符轉義。如果 ensure_ascii 是 false,這些字符會原樣輸出。

如果 check_circular 為 true (默認),那么列表,字典,和自定義編碼的對象在編碼期間會被檢查重復循環引用防止無限遞歸(無限遞歸將導致 OverflowError )。否則,這樣進行檢查。

如果 allow_nan 為 true (默認),那么 NaNInfinity ,和 -Infinity 進行編碼。此行為不符合 JSON 規范,但與大多數的基于 Javascript 的編碼器和解碼器一致。否則,它將是一個 ValueError 來編碼這些浮點數。

如果 sort_keys 為 true (默認為: False ),那么字典的輸出是按照鍵排序;這對回歸測試很有用,以確保可以每天比較 JSON 序列化。

如果 indent 是一個非負整數或者字符串,那么 JSON 數組元素和對象成員會被美化輸出為該值指定的縮進等級。 如果縮進等級為零、負數或者 "",則只會添加換行符。 None (默認值) 選擇最緊湊的表達。 使用一個正整數會讓每一層縮進同樣數量的空格。 如果 indent 是一個字符串 (比如 "\t"),那個字符串會被用于縮進每一層。

在 3.2 版更改: 現允許使用字符串作為 indent 而不再僅僅是整數。

當被指定時,separators 應當是一個 (item_separator, key_separator) 元組。當 indentNone 時,默認值取 (', ', ': '),否則取 (',', ': ')。為了得到最緊湊的 JSON 表達式,你應該指定其為 (',', ':') 以消除空白字符。

在 3.4 版更改: 現當 indent 不是 None 時,采用 (',', ': ') 作為默認值。

default 被指定時,其應該是一個函數,每當某個對象無法被序列化時它會被調用。它應該返回該對象的一個可以被 JSON 編碼的版本或者引發一個 TypeError。如果沒有被指定,則會直接引發 TypeError

在 3.6 版更改: 所有形參現在都是 僅限關鍵字參數

default(o)?

在子類中實現這種方法使其返回 o 的可序列化對象,或者調用基礎實現(引發 TypeError

比如說,為了支持任意迭代器,你可以像這樣實現默認設置:

def default(self, o):
   try:
       iterable = iter(o)
   except TypeError:
       pass
   else:
       return list(iterable)
   # Let the base class default method raise the TypeError
   return json.JSONEncoder.default(self, o)
encode(o)?

返回 Python o 數據結構的 JSON 字符串表達方式。比如說:

>>> json.JSONEncoder().encode({"foo": ["bar", "baz"]})
'{"foo": ["bar", "baz"]}'
iterencode(o)?

編碼給定對象 o ,并且讓每個可用的字符串表達方式。例如:

for chunk in json.JSONEncoder().iterencode(bigobject):
    mysocket.write(chunk)

異常?

exception json.JSONDecodeError(msg, doc, pos)?

擁有以下額外屬性的 ValueError 的子類:

msg?

未格式化的錯誤消息。

doc?

正在解析的 JSON 文檔。

pos?

The start index of doc where parsing failed.

lineno?

The line corresponding to pos.

colno?

The column corresponding to pos.

3.5 新版功能.

標準符合性和互操作性?

JSON 格式由 RFC 7159ECMA-404 指定。此段落詳細講了這個模塊符合 RFC 的級別。簡單來說, JSONEncoderJSONDecoder 子類,和明確提到的參數以外的參數,不作考慮。

此模塊不嚴格遵循于 RFC ,它實現了一些擴展是有效的 Javascript 但不是有效的 JSON。尤其是:

  • 無限和 NaN 數值是可接受的并輸出;

  • 對象內的重復名稱是接受的,并且僅使用最后一對名稱-值對。

自從 RFC 允許符合 RFC 的語法分析程序接收 不符合 RFC 的輸入文本以來,這個模塊的解串器在默認狀態下默認符合 RFC 。

字符編碼?

RFC 要求使用 UTF-8 , UTF-16 ,或 UTF-32 之一來表示 JSON ,為了最大互通性推薦使用 UTF-8 。

RFC允許,盡管不是必須的,這個模塊的序列化默認設置為 ensure_ascii=True ,這樣消除輸出以便結果字符串至容納 ASCII 字符。

ensure_ascii 參數以外,此模塊是嚴格的按照在 Python 對象和 Unicode strings 間的轉換定義的,并且因此不能直接解決字符編碼的問題。

RFC 禁止添加字符順序標記( BOM )在 JSON 文本的開頭,這個模塊的序列化器不添加 BOM 標記在它的輸出上。 RFC,準許 JSON 反序列化器忽略它們輸入中的初始 BOM 標記,但不要求。此模塊的反序列化器引發 ValueError 當出現初始 BOM 標記。

RFC 不會明確禁止包含字節序列的 JSON 字符串這不對應有效的 Unicode 字符(比如 不成對的 UTF-16 的替代物),但是它確實指出它們可能會導致互操作性問題。默認下,模塊對這樣的序列接受和輸出(當在原始 str 存在時)代碼點。

Infinite 和 NaN 數值。?

RFC 不允許 infinite 或者 NaN 數值的表達方式。盡管這樣,默認情況下,此模塊接受并且輸出 Infinity-Infinity,和 NaN 好像它們是有效的JSON數字字面值

>>> # Neither of these calls raises an exception, but the results are not valid JSON
>>> json.dumps(float('-inf'))
'-Infinity'
>>> json.dumps(float('nan'))
'NaN'
>>> # Same when deserializing
>>> json.loads('-Infinity')
-inf
>>> json.loads('NaN')
nan

序列化器中, allow_nan 參數可用于替代這個行為。反序列化器中, parse_constant 參數,可用于替代這個行為。

對象中的重復名稱?

RFC 具體說明了 在 JSON對象里的名字應該是唯一的,但沒有規定如何處理JSON對象中的重復名稱。默認下,此模塊不引發異常;作為替代,對于給定名它將忽略除姓-值對之外的所有對:

>>> weird_json = '{"x": 1, "x": 2, "x": 3}'
>>> json.loads(weird_json)
{'x': 3}

The object_pairs_hook parameter can be used to alter this behavior.

頂級非對象,非數組值?

過時的 RFC 4627 指定的舊版本 JSON 要求 JSON 文本頂級值必須是 JSON 對象或數組( Python dictlist ),并且不能是 JSON null 值,布爾值,數值或者字符串值。 RFC 7159 移除這個限制,此模塊沒有并且從未在序列化器和反序列化器中實現這個限制。

無論如何,為了最大化地獲取互操作性,你可能希望自己遵守該原則。

實現限制?

一些 JSON 反序列化器的實現應該在以下方面做出限制:

  • 接受的 JSON 文本大小

  • 嵌套 JSON 對象和數組的最高水平

  • JSON 數字的范圍和精度

  • JSON 字符串的內容和最大長度

此模塊不強制執行任何上述限制,除了相關的 Python 數據類型本身或者 Python 解釋器本身的限制以外。

當序列化為 JSON ,在應用中當心此類限制這可能破壞你的 JSON 。特別是,通常將 JSON 數字反序列化為 IEEE 754 雙精度數字,從而受到該表示形式的范圍和精度限制。這是特別相關的,當序列化非常大的 Python int 值時,或者當序列化 "exotic" 數值類型的實例時比如 decimal.Decimal

命令行界面?

** 源代碼: ** Lib/json/tool.py


The json.tool module provides a simple command line interface to validate and pretty-print JSON objects.

如果未指定可選的 infileoutfile 參數,則將分別使用 sys.stdinsys.stdout:

$ echo '{"json": "obj"}' | python -m json.tool
{
    "json": "obj"
}
$ echo '{1.2:3.4}' | python -m json.tool
Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

在 3.5 版更改: 輸出現在將與輸入順序保持一致。 請使用 --sort-keys 選項來將輸出按照鍵的字母順序排序。

命令行選項?

infile?

要被驗證或美化打印的 JSON 文件:

$ python -m json.tool mp_films.json
[
    {
        "title": "And Now for Something Completely Different",
        "year": 1971
    },
    {
        "title": "Monty Python and the Holy Grail",
        "year": 1975
    }
]

如果 infile 未指定,則從 sys.stdin 讀取。

outfile?

infile 輸出寫入到給定的 outfile。 在其他情況下寫入到 sys.stdout

--sort-keys?

將字典輸出按照鍵的字母順序排序。

3.5 新版功能.

-h, --help?

顯示幫助消息。

備注

1

正如 RFC 7159 的勘誤表 所說明的,JSON 允許以字符串表示字面值字符 U+2028 (LINE SEPARATOR) 和 U+2029 (PARAGRAPH SEPARATOR),而 JavaScript (在 ECMAScript 5.1 版中) 不允許。