Google App Engine の Model を JSON に変換する方法

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 など