Python 3.0 Hacks

第11回標準になったjsonモジュール

jsonモジュール

WebアプリケーションなどではJavaScriptと連携させることが珍しくないと思います。Python3.0および、Python2.6ではJSON(JavaScript Object Notation)をサポートするためのjsonモジュールが標準として追加されました。これにより、手軽にPythonとJavaScript間でデータのやりとりを行うことができるようになりました。

基本的な使い方

jsonモジュールの基本的な使い方はPickleと同じです。文字列にして返すにはdumps、ファイルオブジェクトの場合はdumpを使用します。同様に、文字列からPythonのオブジェクトにするためにはloadsを使用し、ファイルオブジェクトから読み込む場合にはloadを使います。

リスト1 dumpsを使った例
import json
s = json.dumps( list(range(10)) )
print( type(s), s )

リスト1実行結果
<class 'str'> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

このように、Pythonのオブジェクトを渡すとJSONに変換して文字列として返ってきます。

リスト2 loadsを使った例
t = json.loads( s )
print( type(t), t )

リスト2の実行結果
<class 'list'> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

リスト1でJSON化した文字列をPythonオブジェクトに変換するには、loadsを使用します。

リスト3 dumpを使った例
try:
    from cStringIO import StringIO
except:
    from io import StringIO

buf = StringIO()
json.dump( list(range(10)), buf )
buf.seek( 0 )
u = buf.read()
print( type(u), u )

リスト3の実行結果
<class 'str'> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

リスト3ではファイルオブジェクトの変わりにStringIOを使用し、そこに書き込んでいます。

リスト4 loadを使った例

buf.seek( 0 )
v = json.load( buf )
print( type(v), v )

リスト4の実行結果
<class 'list'> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

日付をエンコードする

日付をやりとりすることは多々ありますが、JSONには日付のフォーマットに関する規定はありません。そのため、jsonモジュールではdatetimeオブジェクトを直接dump、dumpsを行うことはできません。エンコーダを拡張することでエンコードを行えるようなります。

今回は⁠2009-05-31 06:02:20⁠のような形式でやりとりを行うとします。

リスト5 エンコーダの拡張

import json
from datetime import datetime

class DatetimeEncoder(json.JSONEncoder):
    def default(self, obj):
      if isinstance(obj, datetime ):
        return obj.strftime("%Y-%m-%d %H:%M:%S")
      return json.JSONEncoder.default(self, obj)

article = {'title': 'Python 3.0 Hacks', 'time': datetime.now()}
u = json.dumps(article, cls=DatetimeEncoder)
print( type(u), u )

リスト5の実行結果
<class 'str'> {"time": "2009-05-31 06:02:20", "title": "Python 3.0 Hacks"}

これでdatetimeオブジェクトからJSONへ変換することができるようになりました。

日付をデコードする

リスト5で出力した結果をそのままloadしても、日付は文字列のままでdatetimeオブジェクトにはなりません。そこで、今度は日付を読み込んだときに自動的にdatetimeにしてくれるデコード部分を書いてみます。

リスト6 デコーダ部分の作成

def toDatetime(dct):
    if 'time' in dct:
        dct['time'] = datetime.strptime(dct['time'], '%Y-%m-%d %H:%M:%S')
    return dct

v = json.loads(u, object_hook=toDatetime)
print( type(v), v )

リスト6の実行結果
<class 'dict'> {'title': 'Python 3.0 Hacks', 'time': datetime.datetime(2009, 5, 31, 6, 2, 20)}

このように、datetimeオブジェクトに変換されていることがわかります。

まとめ

JSONに変換するモジュールは以前から存在していましたが、今回、標準モジュールとなったことで、今まで以上に気軽に使えるようになったのではないでしょうか。そして、Python3.1ではパフォーマンスの向上を目的として、jsonモジュールがC拡張モジュールとして書き直されるようですWhat's New In Python 3.1⁠。

最近のJavaScriptのライブラリではJSONをサポートしているものが多いですし、その他の言語とのやりとりにも使えるため、JSONは今後もますます使われるライブラリのひとつになるのではないでしょうか。

おすすめ記事

記事・ニュース一覧