19.2. json — JSON エンコーダおよびデコーダ

RFC 4627 で仕様が規定されている JSON (JavaScript Object Notation) は、 JavaScript の文法 (ECMA-262 3rd edition) のサブセットに基いた、軽量データ交換形式です。

json の API は標準ライブラリの marshalpickle のユーザに馴染み深いものです。

基本的な 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, separators=(',', ': ')))
{
    "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 -mjson.tool
{
    "json": "obj"
}
$ echo '{1.2:3.4}' | python -mjson.tool
Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

注釈

JSON は YAML 1.2 のサブセットです。 このモジュールのデフォルト設定 (特に、デフォルトの セパレータ 値) で生成される JSON は YAML 1.0 および 1.1 のサブセットでもあります。 このモジュールは YAML シリアライザとしても使えます。

19.2.1. 基本的な使い方

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) へのストリームとして直列化します。

skipkeysTrue (デフォルトは False) ならば、基本型 (str, int, float, bool, None) 以外の辞書のキーは TypeError を送出せずに読み飛ばされます。

この json モジュールは常に、 bytes オブジェクトではなく、 str オブジェクトを生成します。 従って、 fp.write()str の入力をサポートしていなければなりません。

ensure_ascii が (デフォルト値の) True の場合、出力では入力された全ての非 ASCII 文字はエスケープされていることが保証されています。 ensure_asciiFalse の場合、これらの文字はそのまま出力されます。

check_circularFalse (デフォルトは True) ならば、コンテナ型の循環参照チェックが省かれ、循環参照があれば OverflowError (またはもっと悪い結果) に終わります。

allow_nanFalse (デフォルトは True) ならば、許容範囲外の float 値 (nan, inf, -inf) を直列化しようとした場合、 JSON 仕様を厳格に守って JavaScript の等価なもの (NaN, Infinity, -Infinity) を使うことなく ValueError になります。

indent が非負の整数または文字列であれば、 JSON の配列要素とオブジェクトメンバはそのインデントレベルで見やすく表示されます。 インデントレベルが 0 か負数または "" であれば 改行だけが挿入されます。 None (デフォルト) では最もコンパクトな表現が選択されます。 正の数のindentはレベル毎に、指定した数のスペースでインデントします。 もし indent が文字列 ("\t" のような) であれば、その文字列が個々のレベルのインデントに使用されます。

バージョン 3.2 で変更: 整数に加えて、文字列が indent に使用できるようになりました。

注釈

デフォルトの要素のセパレータが ', ' なので、 indent が指定されたときは出力の末尾に空白文字が付くかもしれません。 これを避けるために separators=(',', ': ') が使えます。

separators がタプル (item_separator, dict_separator) ならば、デフォルト区切り文字 (', ', ': ') の代わりに使われます。 (',', ':') が最もコンパクトな JSON の表現です。

default(obj) は関数で、 obj の直列化可能なバージョンを返すか、さもなくば TypeError を送出します。デフォルトでは単に TypeError を送出します。

sort_keysTrue (デフォルトでは False です)であれば、辞書の出力がキーでソートされます。

カスタマイズされた JSONEncoder のサブクラス (たとえば追加の型を直列化するように default() メソッドをオーバーライドしたもの) を使うには、 cls キーワード引数に指定します; 指定しなければ JSONEncoder が使われます。

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() と同じ意味です。

注釈

picklemarshal とは異なり JSON はフレーム付きのプロトコルではないので、同じ fp に対し繰り返し dump() を呼び、複数のオブジェクトを直列化しようとすると、不正な JSON ファイルが作られてしまいます。

注釈

JSON のキー値ペアのキーは、常に str 型です。 辞書が JSON に変換されるとき、辞書の全てのキーは文字列へ強制的に変換が行われます。 この結果として、辞書が JSON に変換され、それから辞書に戻された場合、辞書は元のものと同じではありません。 つまり文字列ではないキーを持っている場合、 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 ドキュメントを含んでいる file-like object) を Python オブジェクトへ脱直列化します。

object_hook はオプションの関数で、任意のオブジェクトリテラルがデコードされた結果 (dict) に対し呼び出されます。 object_hook の返り値は dict の代わりに使われます。 この機能は独自のデコーダ (例えば JSON-RPC クラスヒンティング) を実装するのに使えます。

object_pairs_hook はオプションで渡す関数で、ペアの順序付きリストのデコード結果に対して呼ばれます。 object_pairs_hook の返り値は dict の代わりに使われます。この機能はキーと値のデコードされる順序に依存する独自のデコーダ (たとえば collections.OrderedDict() は挿入の順序を記憶します) を実装するのに使えます。 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', 'null', 'true', 'false' 。これは不正な JSON 数値に遭遇したときに例外を送出するのに使えます。

バージョン 3.1 で変更: ‘null’, ‘true’, ‘false’ に対して parse_constant は呼びされません。

カスタマイズされた JSONDecoder のサブクラスを使うには、 cls キーワード引数に指定します; 指定しなかった場合は JSONDecoder が使われます。追加のキーワード引数はこのクラスのコンストラクタに引き渡されます。

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 インスタンス) を Python オブジェクトへ脱直列化します。

無視される非推奨の引数 encoding を除いて、その他の引数は load() のものと同じ意味です。

19.2.2. エンコーダとデコーダ

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 の代わりに使われます。この機能はキーと値のデコードされる順序に依存する独自のデコーダ (たとえば collections.OrderedDict() は挿入の順序を記憶します) を実装するのに使えます。 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', 'null', 'true', 'false' 。これは不正な JSON 数値に遭遇したときに例外を送出するのに使えます。

strictFalse (デフォルトは True) の場合、制御文字を文字列に含めることができます。ここで言う制御文字とは、 '\t' (タブ)、 '\n''\r''0' を含む 0-31 の範囲のコードを持つ文字のことです。

脱直列化しようとしているデータが不正な JSON ドキュメントだった場合、 ValueError が送出されます。

decode(s)

s (str インスタンスで JSON 文書を含むもの) の Python 表現を返します。

raw_decode(s)

s (str インスタンスで JSON 文書で始まるもの) から JSON 文書をデコードし、Python 表現と s の文書の終わるところのインデックスからなる 2 要素のタプルを返します。

このメソッドは後ろに余分なデータを従えた文字列から 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 number
True true
False false
None null

このクラスを拡張して他のオブジェクトも認識するようにするには、サブクラスを作って default() メソッドを次のように実装します。もう一つ別のメソッドでオブジェクト o に対する直列化可能なオブジェクトを返すものを呼び出すようにします。変換できない時はスーパークラスの実装を (TypeError を送出させるために) 呼ばなければなりません。

skipkeysFalse (デフォルト) ならば、str, int, float, None 以外のキーをエンコードする試みは TypeError に終わります。 skipkeysTrue の場合は、それらのアイテムは単に読み飛ばされます。

ensure_ascii が (デフォルト値の) True の場合、出力では入力された全ての非 ASCII 文字はエスケープされていることが保証されています。 ensure_asciiFalse の場合、これらの文字はそのまま出力されます。

check_circularTrue (デフォルト) ならば、リスト、辞書および自作でエンコードしたオブジェクトは循環参照がないかエンコード中にチェックされ、無限再帰 (これは OverflowError を引き起こします) を防止します。 True でない場合は、そういったチェックは施されません。

allow_nanTrue (デフォルト) ならば、 NaN, Infinity, -Infinity はそのままエンコードされます。この振る舞いは JSON 仕様に従っていませんが、大半の JavaScript ベースのエンコーダ、デコーダと矛盾しません。 True でない場合は、そのような浮動小数点数をエンコードすると ValueError が送出されます。

sort_keysTrue (デフォルトは False) ならば、辞書の出力がキーでソートされます。これは JSON の直列化がいつでも比較できるようになるので回帰試験の際に便利です。

indent が非負の整数または文字列であれば、 JSON の配列要素とオブジェクトメンバはそのインデントレベルで見やすく表示されます。 インデントレベルが 0 か負数または "" であれば 改行だけが挿入されます。 None (デフォルト) では最もコンパクトな表現が選択されます。 正の数のindentはレベル毎に、指定した数のスペースでインデントします。 もし indent が文字列 ("\t" のような) であれば、その文字列が個々のレベルのインデントに使用されます。

バージョン 3.2 で変更: 整数に加えて、文字列が indent に使用できるようになりました。

注釈

デフォルトの要素のセパレータが ', ' なので、 indent が指定されたときは出力の末尾に空白文字が付くかもしれません。 これを避けるために separators=(',', ': ') が使えます。

separators はもし指定するなら (item_separator, key_separator) というタプルでなければなりません。デフォルトは (', ', ': ') です。最もコンパクトな JSON の表現を得たければ空白を削った (',', ':') を指定すればいいでしょう。

default はもし指定するなら関数で、それがなければ直列化できないオブジェクトに対して呼び出されます。その関数はオブジェクトを JSON でエンコードできるバージョンにして返すか、さもなければ TypeError を送出しなければなりません。

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 をエンコードし、得られた文字列表現ごとに yield します。たとえば:

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

19.2.3. 標準への準拠

JSON 形式の仕様は RFC 4627 で規定されています。 この節では、このモジュールの RFC への準拠水準について詳しく述べます。 簡単のために、 JSONEncoder および JSONDecoder の子クラスと、明示的に触れられていないパラメータについては考慮しないことにします。

このモジュールは、 JavaScript では正しいが JSON では不正ないくつかの拡張が実装されているため、厳密な意味では RFC に準拠していません。特に:

  • オブジェクトでも配列でもない最上位の値を受け付け、また出力します;

  • 無限および NaN の数値を受け付け、また出力します;

  • あるオブジェクト内での同じ名前の繰り返しを受け付け、最後の名前と値のペアの値のみを使用します。

この RFC は、 RFC 準拠のパーサが RFC 準拠でない入力テキストを受け付けることを許容しているので、このモジュールの脱直列化は技術的に言えば、デフォルトの設定では RFC に準拠しています。

19.2.3.1. 文字エンコーディング

RFCは、UTF-8、UTF-16、UTF-32のいずれか(デフォルトはUTF-8)でJSONを表現するよう推奨しています。

RFC で要求ではなく許可されている通り、このモジュールのシリアライザはデフォルトで ensure_ascii=True という設定を用い、従って、結果の文字列が ASCII 文字しか含まないように出力をエスケープします。

ensure_ascii パラメータ以外は、このモジュールは Python オブジェクトと Unicode 文字列 の間の変換において厳密に定義されていて、それ以外のパラメータで文字エンコーディングに関わるものはありません。

19.2.3.2. トップレベルの非オブジェクト、非配列の値の扱い

RFC は JSON テキストのトップレベルの値がJSONオブジェクトか配列 (Python dict または list) でなければならないと規定しています。このモジュールのデシリアライザは単一の JSON の null 、真偽値、数値、文字列の値のみからなる入力テキストを受け付けます。

>>> just_a_json_string = '"spam and eggs"'  # Not by itself a valid JSON text
>>> json.loads(just_a_json_string)
'spam and eggs'

このモジュール自身は、そのような入力テキストを不正だと見なすよう要求する方法までは持っていません。 同じように、このモジュールのシリアライザも Python の Nonebool 値、数値、 str 値を入力として受け付け、例外を送出すること無く、最上位に単体で JSON の null 、真偽値、数値、文字列の値がある出力テキストを生成します:

>>> neither_a_list_nor_a_dict = "spam and eggs"
>>> json.dumps(neither_a_list_nor_a_dict)  # The result is not a valid JSON text
'"spam and eggs"'

このモジュールのシリアライザ自身は前述の制限を強制する方法までは持っていません。

19.2.3.3. 無限および NaN の数値

RFC は、無限もしくは NaN の数値の表現は許可していません。 それにも関わらずデフォルトでは、このモジュールは Infinity-InfinityNaN を正しい 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 パラメータが使えます。

19.2.3.4. オブジェクト中に重複した名前の扱い

RFCはJSONオブジェクト中の名前はユニークでなければならないと規定していますが、JSONオブジェクトで名前が繰り返された場合の扱いについて規定していません。デフォルトでは、このモジュールは例外を送出せず、かわりに重複した名前のうち、最後に出現した名前と値のペア以外を無視します。

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

object_pairs_hook パラメータでこの動作を変更できます