Python Language
JSONモジュール
サーチ…
備考
バージョン固有の機能を含む完全なドキュメントについては、公式ドキュメントを確認してください。
タイプ
デフォルト
json
モジュールはデフォルトで以下の型のエンコーディングとデコードを処理します:
デシリアライゼーションタイプ:
JSON | Python |
---|---|
オブジェクト | dict |
アレイ | リスト |
文字列 | str |
数値(int) | int |
番号(実数) | 浮く |
真偽 | 真偽 |
ヌル | 無し |
json
モジュールは、対応するfloat値としてNaN
、 Infinity
、および-Infinity
も理解しています。これはJSON仕様の範囲外です。
シリアライゼーションタイプ:
Python | JSON |
---|---|
dict | オブジェクト |
リスト、タプル | アレイ |
str | 文字列 |
int、float、(int / float)から継承されたEnums | 数 |
真 | 真実 |
偽 | 偽 |
無し | ヌル |
NaN
、 Infinity
、および-Infinity
エンコードを許可しないには、 allow_nan=False
エンコードする必要があります。これらの値をエンコードしようとすると、 ValueError
ます。
カスタム(デ)シリアル化
異なった表現が必要なデータを扱うためのさまざまなフックがあります。 functools.partial
使用すると、便宜上、これらの関数に関連するパラメータを部分的に適用することができます。
シリアライゼーション:
オブジェクトを直列化する前にオブジェクトで動作する関数を提供することができます。
# my_json module
import json
from functools import partial
def serialise_object(obj):
# Do something to produce json-serialisable data
return dict_obj
dump = partial(json.dump, default=serialise_object)
dumps = partial(json.dumps, default=serialise_object)
デシリアライゼーション:
json関数によって処理される、object_hookやparse_floatなど、さまざまなフックがあります。お使いのPythonのバージョンを網羅したリストは、 こちらをご覧ください 。
# my_json module
import json
from functools import partial
def deserialise_object(dict_obj):
# Do something custom
return obj
def deserialise_float(str_obj):
# Do something custom
return obj
load = partial(json.load, object_hook=deserialise_object, parse_float=deserialise_float)
loads = partial(json.loads, object_hook=deserialise_object, parse_float=deserialise_float)
さらにカスタム(デ)シリアライズ:
json
モジュールでは、 json.JSONEncoder
とjson.JSONDecoder
を拡張/置換してその他の型を処理することもできます。上記のフックは、同等の名前のメソッドを作成することでデフォルトとして追加することができます。これらを使用するには、クラスをcls
パラメータとして関連する関数に渡します。 functools.partial
使用すると、これらの関数にclsパラメータを部分的に適用することができます。
# my_json module
import json
from functools import partial
class MyEncoder(json.JSONEncoder):
# Do something custom
class MyDecoder(json.JSONDecoder):
# Do something custom
dump = partial(json.dump, cls=MyEncoder)
dumps = partial(json.dumps, cls=MyEncoder)
load = partial(json.load, cls=MyDecoder)
loads = partial(json.loads, cls=MyDecoder)
Python dictからJSONを作成する
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
json.dumps(d)
上記のスニペットは、以下を返します:
'{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
JSONからPython dictを作成する
import json
s = '{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
json.loads(s)
上記のスニペットは、以下を返します:
{u'alice': 1, u'foo': u'bar', u'wonderland': [1, 2, 3]}
データをファイルに保存する
次のスニペットは、 d
に格納されたデータをJSONにエンコードし、ファイルに格納します( filename
を実際のfilename
で置き換えます)。
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
with open(filename, 'w') as f:
json.dump(d, f)
ファイルからのデータの取得
次のスニペットは、JSONでエンコードされたファイルを開き( filename
を実際のfilename
で置き換えます)、ファイルに格納されているオブジェクトを返します。
import json
with open(filename, 'r') as f:
d = json.load(f)
`load`と` dump`と `dump`と` dump '
json
モジュールには、Unicode文字列の読み取りと書き込み、およびファイルの読み書きを行うための関数が含まれています。これらは、関数名の末尾にs
で区別されます。これらの例では、StringIOオブジェクトを使用していますが、同じ関数がファイルのようなオブジェクトにも適用されます。
ここでは、文字列ベースの関数を使用します。
import json
data = {u"foo": u"bar", u"baz": []}
json_string = json.dumps(data)
# u'{"foo": "bar", "baz": []}'
json.loads(json_string)
# {u"foo": u"bar", u"baz": []}
ここではファイルベースの関数を使用します:
import json
from io import StringIO
json_file = StringIO()
data = {u"foo": u"bar", u"baz": []}
json.dump(data, json_file)
json_file.seek(0) # Seek back to the start of the file before reading
json_file_content = json_file.read()
# u'{"foo": "bar", "baz": []}'
json_file.seek(0) # Seek back to the start of the file before reading
json.load(json_file)
# {u"foo": u"bar", u"baz": []}
主な違いがわかるように、jsonデータをダンプするときは、戻り値を取り込むのではなく、ファイルハンドルを関数に渡す必要があります。また、データの破壊を避けるために、読み書きの前にファイルの先頭に目を向ける必要があることにも注意してください。ファイルを開くとき、カーソルは位置0
に置かれるので、以下も有効です:
import json
json_file_path = './data.json'
data = {u"foo": u"bar", u"baz": []}
with open(json_file_path, 'w') as json_file:
json.dump(data, json_file)
with open(json_file_path) as json_file:
json_file_content = json_file.read()
# u'{"foo": "bar", "baz": []}'
with open(json_file_path) as json_file:
json.load(json_file)
# {u"foo": u"bar", u"baz": []}
jsonデータを扱う両方の方法を持つことで、 pyspark
のjson-per-lineのようにjsonをpyspark
したフォーマットで慣用的かつ効率的に作業することができます。
# loading from a file
data = [json.loads(line) for line in open(file_path).splitlines()]
# dumping to a file
with open(file_path, 'w') as json_file:
for item in data:
json.dump(item, json_file)
json_file.write('\n')
コマンドラインからJSON出力をきれいに印刷するために `json.tool`を呼び出します
次のようなJSONファイル "foo.json"があるとします。
{"foo": {"bar": {"baz": 1}}}
モジュールをコマンドラインから直接呼び出すことができます(ファイル名を引数として渡して)、それをきれいに印刷することができます:
$ python -m json.tool foo.json
{
"foo": {
"bar": {
"baz": 1
}
}
}
モジュールはSTDOUTからの入力も受け取りますので、(Bashでは)同じことができます:
$ cat foo.json | python -m json.tool
JSON出力の書式設定
次のデータがあるとします。
>>> data = {"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
これをJSONとしてダンプするだけで、特別なことはありません:
>>> print(json.dumps(data))
{"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
よりきれいな出力を得るためにインデントを設定する
きれいな印刷をしたい場合は、 indent
サイズを設定することができます:
>>> print(json.dumps(data, indent=2))
{
"cats": [
{
"name": "Tubbs",
"color": "white"
},
{
"name": "Pepper",
"color": "black"
}
]
}
一貫した出力を得るためにアルファベット順にキーを並べ替える
デフォルトでは、出力のキーの順序は未定義です。私たちはいつも同じ出力を得るためにアルファベット順にそれらを得ることができます:
>>> print(json.dumps(data, sort_keys=True))
{"cats": [{"color": "white", "name": "Tubbs"}, {"color": "black", "name": "Pepper"}]}
コンパクトな出力を得るために空白を取り除く
デフォルトの', '
と': '
とは異なるセパレータ文字列を設定することで、不要なスペースを取り除きたいかもしれません:
>>>print(json.dumps(data, separators=(',', ':')))
{"cats":[{"name":"Tubbs","color":"white"},{"name":"Pepper","color":"black"}]}
カスタムオブジェクトをエンコードするJSON
私たちが次のことを試してみたら:
import json
from datetime import datetime
data = {'datetime': datetime(2016, 9, 26, 4, 44, 0)}
print(json.dumps(data))
TypeError: datetime.datetime(2016, 9, 26, 4, 44) is not JSON serializable
というエラーが表示TypeError: datetime.datetime(2016, 9, 26, 4, 44) is not JSON serializable
ます。
datetimeオブジェクトを適切にシリアル化できるようにするには、変換方法のカスタムコードを記述する必要があります。
class DatetimeJSONEncoder(json.JSONEncoder):
def default(self, obj):
try:
return obj.isoformat()
except AttributeError:
# obj has no isoformat method; let the builtin JSON encoder handle it
return super(DatetimeJSONEncoder, self).default(obj)
json.dumps
代わりにこのエンコーダクラスを使用します。
encoder = DatetimeJSONEncoder()
print(encoder.encode(data))
# prints {"datetime": "2016-09-26T04:44:00"}