Google App Engine (以下 GAE) で結果を JSON で出力したい場合、GAE SDK に同梱されている Django の simplejson を使えばいい。ただ問題があって、simplejson で JSON にできるのは、Python の組み込み型*1だけ。Model や GqlQuery を JSON にはできない。
対応策として思いついたのは、Model や Query の内容を dict に詰める方法と、カスタム JSONEncoder を作る方法の2つ。私が選択したのは後者。
class GaeEncoder(simplejson.JSONEncoder): def default(self, obj): if hasattr(obj, '__json__'): return getattr(obj, '__json__')() # db.Query に対応 if isinstance(obj, db.Query): return list(obj) if isinstance(obj, db.GqlQuery): return list(obj) elif isinstance(obj, db.Model): properties = obj.properties().items() output = {} for field, value in properties: output[field] = getattr(obj, field) return output # datetime は単純な文字列にする elif isinstance(obj, datetime.datetime): return str(obj) elif isinstance(obj, time.struct_time): return list(obj) elif isinstance(obj, users.User): output = {} methods = ['nickname', 'email', 'auth_domain'] for method in methods: output[method] = getattr(obj, method)() return output return simplejson.JSONEncoder.default(self, obj) def encode(obj): return GaeEncoder().encode(obj)
Google Code に GAE で JSON を出力するサンプルがあったので、それを改変。datetime は単純に文字列化して、あと Query にも対応してみた。
GAE で Web API を作る場合、出力のフォーマットは JSON か XML を選択すると思うので、GAE SDK にユーティリティクラスを追加して欲しいところだ。Kay Framework とかでもいいけど。
*1:int、str、dict、list など