19.2. json
--- JSON エンコーダおよびデコーダ¶
ソースコード: Lib/json/__init__.py
JSON (JavaScript Object Notation) は、 RFC 7159 (RFC 4627 を obsolete) と ECMA-404 によって定義された軽量のデータ交換用のフォーマットです。 JavaScript のオブジェクトリテラル記法に由来しています (JavaScript の厳密なサブセットではありませんが [1])。
json
の API は標準ライブラリの marshal
や pickle
のユーザに馴染み深いものです。
基本的な 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)
というタプルでなければなりません。デフォルトは indent がNone
のとき(', ', ': ')
で、そうでなければ(',', ': ')
です。最もコンパクトな JSON の表現を得たければ空白を削った(',', ':')
を指定すればいいでしょう。バージョン 3.4 で変更: indent が
None
でなければ(',', ': ')
がデフォルトで使われます。default を指定する場合は関数を指定して、この関数はそれ以外では直列化できないオブジェクトに対して呼び出されます。 その関数は、オブジェクトを JSON でエンコードできるバージョンにして返すか、さもなければ
TypeError
を送出しなければなりません。 指定しない場合は、TypeError
が送出されます。sort_keys が true (デフォルトでは
False
です)であれば、辞書の出力がキーでソートされます。カスタマイズされた
JSONEncoder
のサブクラス (たとえば追加の型を直列化するようにdefault()
メソッドをオーバーライドしたもの) を使うには、 cls キーワード引数に指定します; 指定しなければJSONEncoder
が使われます。バージョン 3.6 で変更: すべてのオプション引数は、 キーワード専用引数 になりました。
-
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()
と同じ意味です。注釈
pickle
やmarshal
とは異なり 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)¶ Deserialize fp (a
.read()
-supporting file-like object containing a JSON document) to a Python object using this conversion table.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 で変更: すべてのオプション引数は、 キーワード専用引数 になりました。
-
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
が送出されます。
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
が送出されます。
-
-
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)
というタプルでなければなりません。デフォルトは indent がNone
のとき(', ', ': ')
で、そうでなければ(',', ': ')
です。最もコンパクトな 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 をエンコードし、得られた文字列表現ごとに yield します。たとえば:
for chunk in json.JSONEncoder().iterencode(bigobject): mysocket.write(chunk)
-
19.2.3. 例外¶
19.2.4. 標準への準拠と互換性¶
JSON 形式の仕様は RFC 7159 と ECMA-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
、-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 パラメータが使えます。
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 での dict
か list
)であることを要求していて、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.stdin
と sys.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) が文字列内に含まれることを許容しています。 |