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

ソースコード: Lib/json/__init__.py


JSON (JavaScript Object Notation) は、 RFC 7159 (RFC 4627 を obsolete) と ECMA-404 によって定義された軽量のデータ交換用のフォーマットです。 JavaScript のオブジェクトリテラル記法に由来しています (JavaScript の厳密なサブセットではありませんが 1)。

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

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

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

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

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

allow_nan が偽 (デフォルトは True) の場合、許容範囲外の float 値 (nan, inf, -inf) を JSON 仕様を厳格に守って 直列化すると、ValueError になります。 allow_non が真の場合は、 JavaScript での等価なもの (NaN, Infinity, -Infinity) が使われます。

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

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

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

バージョン 3.4 で変更: indentNone でなければ (',', ': ') がデフォルトで使われます。

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 に変換され、それから辞書に戻された場合、辞書は元のものと同じではありません。つまり文字列ではないキーを持っている場合、 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 の代わりに使われます。この機能はキーと値のデコードされる順序に依存する独自のデコーダ (たとえば 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 ドキュメントだった場合、 JSONDecodeError が送出されます。

バージョン 3.6 で変更: すべてのオプション引数は、 キーワード専用引数 になりました。

バージョン 3.6 で変更: fp には term: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, bytes, bytearray のいずれかのインスタンス) を Python オブジェクトへ脱直列化します。

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

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

バージョン 3.6 で変更: s には bytes 型と bytearray 型も使えるようになりました。 入力エンコーディングは UTF-8, UTF-16, UTF-32 のいずれかでなければなりません。

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)

浮動小数点数

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 数値に遭遇したときに例外を送出するのに使えます。

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

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

バージョン 3.6 で変更: すべての引数は、 キーワード専用引数 になりました。

decode(s)

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

不正な JSON ドキュメントが与えられた場合、 JSONDecodeError が送出されます。

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 と int や float の派生列挙型

number

True

true

False

false

None

null

バージョン 3.4 で変更: int と float の派生列挙型クラスの対応が追加されました。

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

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

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

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

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

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

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

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

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

バージョン 3.4 で変更: indentNone でなければ (',', ': ') がデフォルトで使われます。

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

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

19.2.3. 例外

exception json.JSONDecodeError(msg, doc, pos)

ValueError のサブクラスで、以下の追加の属性を持ちます:

msg

フォーマットされていないエラーメッセージです。

doc

パース対象 JSON ドキュメントです。

pos

doc の、解析に失敗した開始インデクスです。

lineno

pos に対応する行です。

colno

pos に対応する列です。

バージョン 3.5 で追加.

19.2.4. 標準への準拠と互換性

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

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

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

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

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

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

RFC は、UTF-8、UTF-16、UTF-32のいずれかでJSONを表現するように要求しており、UTF-8 が最大の互換性を確保するために推奨されるデフォルトです。

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

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

RFC は JSON テキストの最初にバイトオーダマーク(BOM)を追加することを禁止していますので、このモジュールはその出力に BOM を追加しません。RFC は JSON デシリアライザが入力の一番最初の BOM を無視することを、許容はしますが求めてはいません。このモジュールのデシリアライザは一番最初の BOM を見つけると ValueError を送出します。

RFC は JSON 文字列に正当な Unicode 文字に対応付かないバイト列(例えばペアにならない UTF-16 サロゲートのかたわれ)が含まれることを明示的に禁止してはおらず、もちろんこれは相互運用性の問題を引き起こします。デフォルトでは、このモジュールは(オリジナルの str にある場合)そのようなシーケンスのコードポイントを受け取り、出力します。

19.2.4.2. 無限および 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.4.3. オブジェクト中に重複した名前の扱い

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

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

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

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

廃止された RFC 4627 によって規定された古いバージョンの JSON では、JSON テキストのトップレベルの値は JSON オブジェクトか配列(Python での dictlist)であることを要求していて、JSON の null, boolean, number, string であることは許されていませんでしたが、この制限は RFC 7159 により取り払われました。このモジュールはこの制限を持っていませんし、シリアライザでもデシリアライズでも、一度としてこの制限で実装されたことはありません。

それにも関わらず、相互運用可能性を最大化したいならば、あなた自身の手で自発的にその制約に忠実に従いたいと思うでしょう。

19.2.4.5. 実装の制限

いくつかの JSON デシリアライザの実装は、以下の制限を設定することがあります。

  • 受け入れられる JSON テキストのサイズ

  • JSON オブジェクトと配列のネストの最大の深さ

  • JSON 数値の範囲と精度

  • JSON 文字列の内容と最大の長さ

このモジュールは関連する Python データ型や Python インタプリタ自身の制約の世界を超えたそのような制約を強要はしません。

JSON にシリアライズする際には、あなたの JSON を消費する側のアプリケーションが持つ当該制約に思いを馳せてください。とりわけJSON 数値を IEEE 754 倍精度浮動小数にデシリアライズする際の問題はありがちで、すなわちその有効桁数と精度の制限の影響を受けます。これは、極端に大きな値を持った Python int をシリアライズするとき、あるいは decimal.Decimal のような "風変わりな" 数値型をシリアライズするとき、に特に関係があります。

19.2.5. コマンドラインインターフェイス

ソースコード: Lib/json/tool.py


json.tool モジュールは JSON オブジェクトの検証と整形出力のための、単純なコマンドラインインターフェイスを提供します。

オプショナルな infile 引数、 outfile 引数が指定されない場合、それぞれ 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 オプションを使ってください。

19.2.5.1. コマンドラインオプション

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 は (ECMAScript Edition 5.1 の) JavaScript とは逆に、 U+2028 (LINE SEPARATOR) と U+2029 (PARAGRAPH SEPARATOR) が文字列内に含まれることを許容しています。