18.2. json
— JSON エンコーダおよびデコーダ¶
バージョン 2.6 で追加.
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(u'\u1234')
"\u1234"
>>> print json.dumps('\\')
"\\"
>>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
{"a": 0, "b": 0, "c": 0}
>>> from StringIO 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]}]')
[u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
>>> json.loads('"\\"foo\\bar"')
u'"foo\x08ar'
>>> from StringIO import StringIO
>>> io = StringIO('["streaming API"]')
>>> json.load(io)
[u'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 -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 シリアライザとしても使えます。
18.2.1. 基本的な使い方¶
-
json.
dump
(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)¶ この 変換表 を使って、 obj を JSON 形式の fp (
.write()
がサポートされている file-like object) へのストリームとして直列化します。skipkeys が真 (デフォルトは
False
) ならば、基本型 (str
,unicode
,int
,long
,float
,bool
,None
) 以外の辞書のキーはTypeError
を送出せずに読み飛ばされます。ensure_ascii が真 (これがデフォルトです) ならば全ての非 ASCII 文字は出力において
\uXXXX
エスケープされて、結果は ASCII 文字のみからなるstr
インスタンスになります。 ensure_ascii が偽の場合、 fp へ書き込まれるチャンクはunicode
インスタンスになることがあります。これは普通は入力に Unicode 文字列を含むか、 encoding パラメータを使う場合に起こります。fp.write()
が (codecs.getwriter()
でのように)unicode
であると明示的に理解していない限り、これはエラーを引き起こすかもしれません。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 が指定されたときは出力の末尾に空白文字が付くかもしれません。これを避けるためにseparators=(',', ': ')
が使えます。separators を指定する場合は、
(item_separator, key_separator)
というタプルでなければなりません。デフォルトでは(', ', ': ')
が使われます。最もコンパクトな JSON の表現を得たければ空白を削った(',', ':')
を指定すればいいでしょう。encoding は文字列のエンコーディングで、デフォルトは UTF-8 です。
default を指定する場合は関数を指定して、この関数はそれ以外では直列化できないオブジェクトに対して呼び出されます。その関数は、オブジェクトを JSON でエンコードできるバージョンにして返すか、さもなければ
TypeError
を送出しなければなりません。指定しない場合は、TypeError
が送出されます。sort_keys が true (デフォルトでは
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, encoding="utf-8", default=None, sort_keys=False, **kw)¶ この 変換表 を使って、 obj を JSON 形式の
str
オブジェクトに直列化します。 ensure_ascii が偽の場合は、結果は非 ASCII を含むかもしれず、戻り値がunicode
のインスタンスになることがあります。引数は
dump()
のものと同じ意味になります。注釈
JSON のキー値ペアのキーは、常に
str
型です。辞書が JSON に変換されるとき、辞書の全てのキーは文字列へ強制的に変換が行われます。この結果として、辞書が JSON に変換され、それから辞書に戻された場合、辞書は元のものと同じではありません。つまり文字列ではないキーを持っている場合、loads(dumps(x)) != x
となるということです。
-
json.
load
(fp[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])¶ この 変換表 を使い、 fp (
.read()
をサポートし JSON ドキュメントを含んでいる file-like object) を Python オブジェクトへ脱直列化します。fp の内容が ASCII に基づいたしかし UTF-8 ではないエンコーディング (たとえば latin-1) を使っているならば、適切な encoding 名が指定されなければなりません。エンコーディングが ASCII に基づかないもの (UCS-2 など) であることは許されないので、
codecs.getreader(encoding)(fp)
というように包むか、または単にunicode
オブジェクトにデコードしたものをloads()
に渡して下さい。object_hook はオプションの関数で、任意のオブジェクトリテラルがデコードされた結果 (
dict
) に対し呼び出されます。 object_hook の返り値はdict
の代わりに使われます。この機能は独自のデコーダ (例えば JSON-RPC クラスヒンティング) を実装するのに使えます。object_pairs_hook はオプションで渡す関数で、ペアの順序付きリストのデコード結果に対して呼ばれます。 object_pairs_hook の返り値は
dict
の代わりに使われます。この機能はキーと値のデコードされる順序に依存する独自のデコーダ (たとえばcollections.OrderedDict()
は挿入の順序を記憶します) を実装するのに使えます。 object_hook も定義されている場合は、 object_pairs_hook が優先して使用されます。バージョン 2.7 で変更: 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 数値に遭遇したときに例外を送出するのに使えます。バージョン 2.7 で変更: 'null', 'true', 'false' に対して parse_constant は呼びされません。
カスタマイズされた
JSONDecoder
のサブクラスを使うには、 cls キーワード引数に指定します; 指定しなかった場合はJSONDecoder
が使われます。追加のキーワード引数はこのクラスのコンストラクタに引き渡されます。
-
json.
loads
(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])¶ この 変換表 を使い、 s (JSON ドキュメントを含んでいる
str
またはunicode
のインスタンス) を Python オブジェクトへ脱直列化します。s が ASCII に基づいたしかし UTF-8 ではないエンコーディング (たとえば latin-1) でエンコードされた
str
ならば、適切な encoding 名が指定されなければなりません。エンコーディングが ASCII に基づかないもの (UCS-2 など) であることは許されないので、まずunicode
にデコードして下さい。その他の引数は
load()
のものと同じ意味です。
18.2.2. エンコーダとデコーダ¶
-
class
json.
JSONDecoder
([encoding[, object_hook[, parse_float[, parse_int[, parse_constant[, strict[, object_pairs_hook]]]]]]])¶ 単純な JSON デコーダ。
デフォルトではデコーディングの際、以下の変換を行います:
JSON Python object dict array list string unicode number (int) int, long number (real) float true True false False null None また、このデコーダは
NaN
,Infinity
,-Infinity
を対応するfloat
の値として、JSON の仕様からは外れますが、理解します。encoding はこのインスタンスでデコードされる
str
オブジェクトを解釈するために使われるエンコーディング (デフォルトは UTF-8) を定めます。unicode
オブジェクトのデコーディングには影響を与えません。注意して欲しいのは現状では ASCII のスーパーセットであるようなエンコーディングだけうまく動くということです。他のエンコーディングの文字列は
unicode
にして渡して下さい。object_hook は、もし指定されれば、全てのデコードされた JSON オブジェクトに対して呼ばれその返値は与えられた
dict
の代わりに使われます。この機能は独自の脱直列化 (たとえば JSON-RPC クラスヒンティングをサポートするような) を提供するのに使えます。object_pairs_hook は、もし指定されれば、全てのペアの順序付きリストにデコードされた JSON オブジェクトに対して呼ばれます。 object_pairs_hook の返り値は
dict
の代わりに使われます。この機能はキーと値のデコードされる順序に依存する独自のデコーダ (たとえばcollections.OrderedDict()
は挿入の順序を記憶します) を実装するのに使えます。 object_hook も定義されている場合は、 object_pairs_hook が優先して使用されます。バージョン 2.7 で変更: 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 ドキュメントだった場合、
ValueError
が送出されます。
-
class
json.
JSONEncoder
([skipkeys[, ensure_ascii[, check_circular[, allow_nan[, sort_keys[, indent[, separators[, encoding[, default]]]]]]]]])¶ Python データ構造に対する拡張可能な JSON エンコーダ。
デフォルトでは以下のオブジェクトと型をサポートします:
Python JSON dict object list, tuple array str, unicode string int, long, float number True true False false None null このクラスを拡張して他のオブジェクトも認識するようにするには、サブクラスを作って
default()
メソッドを次のように実装します。もう一つ別のメソッドでオブジェクトo
に対する直列化可能なオブジェクトを返すものを呼び出すようにします。変換できない時はスーパークラスの実装を (TypeError
を送出させるために) 呼ばなければなりません。skipkeys が偽 (デフォルト) ならば、str, int, long, float,
None
以外のキーをエンコードする試みはTypeError
に終わります。 skipkeys が真の場合は、それらのアイテムは単に読み飛ばされます。ensure_ascii が真 (これがデフォルトです) の場合、全ての非 ASCII 文字は出力において
\uXXXX
エスケープされて、結果は ASCII 文字のみからなるstr
インスタンスになります。 ensure_ascii が偽の場合、 結果はunicode
インスタンスになることがあります。これは普通は入力に Unicode 文字列を含むか、 encoding パラメータを使う場合に起こります。check_circular が true (デフォルト) ならば、リスト、辞書および自作でエンコードしたオブジェクトは循環参照がないかエンコード中にチェックされ、無限再帰 (これは
OverflowError
を引き起こします) を防止します。True
でない場合は、そういったチェックは施されません。allow_nan が true (デフォルト) ならば、
NaN
,Infinity
,-Infinity
はそのままエンコードされます。この振る舞いは JSON 仕様に従っていませんが、大半の JavaScript ベースのエンコーダ、デコーダと矛盾しません。True
でない場合は、そのような浮動小数点数をエンコードするとValueError
が送出されます。sort_keys が true (デフォルトは
False
) ならば、辞書の出力がキーでソートされます。これは JSON の直列化がいつでも比較できるようになるので回帰試験の際に便利です。indent が非負の整数であれば (デフォルトは
None
です)、JSON の配列要素とオブジェクトメンバはそのインデントレベルで見やすく表示されます。インデントレベルが 0 であれば 改行だけが挿入されます。None
では最もコンパクトな表現が選択されます。注釈
デフォルトの要素のセパレータが
', '
なので、 indent が指定されたときは出力の末尾に空白文字が付くかもしれません。これを避けるためにseparators=(',', ': ')
が使えます。separators を指定する場合は、
(item_separator, key_separator)
というタプルでなければなりません。デフォルトでは(', ', ': ')
が使われます。最もコンパクトな JSON の表現を得たければ空白を削った(',', ':')
を指定すればいいでしょう。default を指定する場合は関数を指定して、この関数はそれ以外では直列化できないオブジェクトに対して呼び出されます。その関数は、オブジェクトを JSON でエンコードできるバージョンにして返すか、さもなければ
TypeError
を送出しなければなりません。指定しない場合は、TypeError
が送出されます。encoding が
None
でなければ、入力文字列は全て JSON エンコーディングに先立ってこのエンコーディングで Unicode に変換されます。デフォルトは UTF-8 です。-
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 JSONEncoder.default(self, o)
-
encode
(o)¶ Python データ構造 o の JSON 文字列表現を返します。たとえば:
>>> JSONEncoder().encode({"foo": ["bar", "baz"]}) '{"foo": ["bar", "baz"]}'
-
iterencode
(o)¶ 与えられたオブジェクト o をエンコードし、得られた文字列表現ごとに yield します。たとえば:
for chunk in JSONEncoder().iterencode(bigobject): mysocket.write(chunk)
-
18.2.3. 標準への準拠と互換性¶
JSON 形式の仕様は RFC 7159 と ECMA-404 で規定されています。 この節では、このモジュールの RFC への準拠水準について詳しく述べます。 簡単のために、 JSONEncoder
および JSONDecoder
の子クラスと、明示的に触れられていないパラメータについては考慮しないことにします。
このモジュールは、JavaScript では正しいが JSON では不正ないくつかの拡張が実装されているため、厳密な意味では RFC に準拠していません。特に:
- 無限および NaN の数値を受け付け、また出力します;
- あるオブジェクト内での同じ名前の繰り返しを受け付け、最後の名前と値のペアの値のみを使用します。
この RFC は、RFC 準拠のパーサが RFC 準拠でない入力テキストを受け付けることを許容しているので、このモジュールの脱直列化は技術的に言えば、デフォルトの設定では RFC に準拠しています。
18.2.3.1. 文字エンコーディング¶
RFC は、UTF-8、UTF-16、UTF-32のいずれかでJSONを表現するように要求しており、UTF-8 が最大の互換性を確保するために推奨されるデフォルトです。このため、このモジュールは encoding パラメータのデフォルトに UTF-8 を使います。
このモジュールのデシリアライザは直接的には、ASCII 互換のエンコーディングでのみ動作します。UTF-16, UTF-32 やほかの ASCII 非互換のエンコーディングには、このドキュメント内でデシリアライザの encoding パラメータについて説明した回避方法を取る必要があります。
RFC で要求ではなく許可されている通り、このモジュールのシリアライザはデフォルトで ensure_ascii=True という設定を用い、従って、結果の文字列が ASCII 文字しか含まないように出力をエスケープします。
RFC は JSON テキストの最初にバイトオーダマーク(BOM)を追加することを禁止していますので、このモジュールはその出力に BOM を追加しません。RFC は JSON デシリアライザが入力の一番最初の BOM を無視することを、許容はしますが求めてはいません。このモジュールのデシリアライザは一番最初の BOM を見つけると ValueError
を送出します。
RFC は JSON 文字列に正当な Unicode 文字に対応付かないバイト列(例えばペアにならない UTF-16 サロゲートのかたわれ)が含まれることを明示的に禁止してはおらず、もちろんこれは相互運用性の問題を引き起こします。デフォルトでは、このモジュールは(オリジナルの str
にある場合)そのようなシーケンスのコードポイントを受け取り、出力します。
18.2.3.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 パラメータが使えます。
18.2.3.3. オブジェクト中に重複した名前の扱い¶
RFC は JSON オブジェクト中の名前はユニークでなければならないと規定していますが、JSONオブジェクトで名前が繰り返された場合の扱いについて指定していません。デフォルトでは、このモジュールは例外を送出せず、かわりに重複した名前のうち、最後に出現した名前と値のペア以外を無視します。
>>> weird_json = '{"x": 1, "x": 2, "x": 3}'
>>> json.loads(weird_json)
{u'x': 3}
object_pairs_hook パラメータでこの動作を変更できます。
18.2.3.4. トップレベルの非オブジェクト、非配列の値の扱い¶
廃止された RFC 4627 によって規定された古いバージョンの JSON では、JSON テキストのトップレベルの値は JSON オブジェクトか配列(Python での dict
か list
)であることを要求していて、JSON の null, boolean, number, string であることは許されていませんでしたが、この制限は RFC 7159 により取り払われました。このモジュールはこの制限を持っていませんし、シリアライザでもデシリアライズでも、一度としてこの制限で実装されたことはありません。
それにも関わらず、相互運用可能性を最大化したいならば、あなた自身の手で自発的にその制約に忠実に従いたいと思うでしょう。
18.2.3.5. 実装の制限¶
いくつかの JSON デシリアライザの実装は、以下の制限を設定することがあります。
- 受け入れられる JSON テキストのサイズ
- JSON オブジェクトと配列のネストの最大の深さ
- JSON 数値の範囲と精度
- JSON 文字列の内容と最大の長さ
このモジュールは関連する Python データ型や Python インタプリタ自身の制約の世界を超えたそのような制約を強要はしません。
JSON にシリアライズする際には、あなたの JSON を消費する側のアプリケーションが持つ当該制約に思いを馳せてください。とりわけJSON 数値を IEEE 754 倍精度浮動小数にデシリアライズする際の問題はありがちで、すなわちその有効桁数と精度の制限の影響を受けます。これは、極端に大きな値を持った Python int
をシリアライズするとき、あるいは decimal.Decimal
のような "風変わりな" 数値型をシリアライズするとき、に特に関係があります。
注記
[1] | RFC 7159 正誤表 で述べられている通り、JSON は (ECMAScript Edition 5.1 の) JavaScript とは逆に、 U+2028 (LINE SEPARATOR) と U+2029 (PARAGRAPH SEPARATOR) が文字列内に含まれることを許容しています。 |