19

使用時

from django.utils import simplejson

それから派生しdb.Modelた型のオブジェクトでは、例外がスローされます。これを回避する方法は?

4

5 に答える 5

14

わかりました-私のpythonはあまり良くないので、助けていただければ幸いです-パーサーを書く必要はありません-これが解決策です:

このユーティリティ クラスを追加します http://code.google.com/p/google-app-engine-samples/source/browse/trunk/geochat/json.py?r=55

 import datetime  
 import time 

 from google.appengine.api import users 
 from google.appengine.ext import db 

#this is a mod on the orinal file for some reason it includes its own simplejson files i have ref django!
 from django.utils import simplejson  

 class GqlEncoder(simplejson.JSONEncoder): 

   """Extends JSONEncoder to add support for GQL results and properties. 

   Adds support to simplejson JSONEncoders for GQL results and properties by 
   overriding JSONEncoder's default method. 
   """ 

   # TODO Improve coverage for all of App Engine's Property types. 

   def default(self, obj): 

     """Tests the input object, obj, to encode as JSON.""" 

     if hasattr(obj, '__json__'): 
       return getattr(obj, '__json__')() 

     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 

     elif isinstance(obj, datetime.datetime): 
       output = {} 
       fields = ['day', 'hour', 'microsecond', 'minute', 'month', 'second', 
           'year'] 
       methods = ['ctime', 'isocalendar', 'isoformat', 'isoweekday', 
           'timetuple'] 
       for field in fields: 
         output[field] = getattr(obj, field) 
       for method in methods: 
         output[method] = getattr(obj, method)() 
       output['epoch'] = time.mktime(obj.timetuple()) 
       return output 

     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(input): 
   """Encode an input GQL object as JSON 

     Args: 
       input: A GQL object or DB property. 

     Returns: 
       A JSON string based on the input object.  

     Raises: 
       TypeError: Typically occurs when an input object contains an unsupported 
         type. 
     """ 
   return GqlEncoder().encode(input)   

json.py として保存

使用する

import cgi
import os
import json 

from google.appengine.ext.webapp import template
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db


class Greeting(db.Model):
    author = db.UserProperty()
    content = db.StringProperty(multiline=True)
    date = db.DateTimeProperty(auto_now_add=True)

class MainPage(webapp.RequestHandler):
    def get(self):
        greetings_query = Greeting.all().order('-date')
        greetings = greetings_query.fetch(5)

        if users.get_current_user():
            url = users.create_logout_url(self.request.uri)
            url_linktext = 'Logout'
        else:
            url = users.create_login_url(self.request.uri)
            url_linktext = 'Login'

        template_values = {
            'greetings': greetings,
            'url': url,
            'url_linktext': url_linktext,
            }

        path = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(path, template_values))


class Guestbook(webapp.RequestHandler):
    def post(self):
        greeting = Greeting()

        if users.get_current_user():
            greeting.author = users.get_current_user()

        greeting.content = self.request.get('content')
        greeting.put()
        self.redirect('/')



#here i return my json feed - simple implementaion for example
class FeedHandler(webapp.RequestHandler):

  def get(self):
    """Retrieve a feed"""
    user = None

    greetings_query = Greeting.all().order('-date')
    rs= greetings_query.fetch(5)
#this is the part that calls the encoder - dosnt cause an exception
    data = json.encode(rs)



#roll out to browser -might need to check my headers etc
    self.response.headers['Content-Type'] = 'application/json; charset=utf-8'  
    self.response.out.write(data)




application = webapp.WSGIApplication(
                                       [
                                       ('/', MainPage),
                                       ('/sign',Guestbook),
                                       ('/feed',FeedHandler),
                                       ], debug=True
                                    )

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

これはブラウザの応答です。

[{"content": "", "date": {"ctime": "Sat Jan 23 02:40:22 2010", "hour": 2, "isoweekday": 6, "month": 1, "second ": 22, "マイクロ秒": 434000, "isocalendar": [2010, 3, 6], "timetuple": [2010, 1, 23, 2, 40, 22, 5, 23, -1], "年" : 2010、"エポック": 1264214422.0、"isoformat": "2010-01-23T02:40:22.434000"、"日": 23、"分": 40}、"作成者": {"ニックネーム": "test@ example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "", "date": {"ctime": "Sat Jan 23 01:12:43 2010", "時間": 1, "isoweekday": 6, "月": 1,"second": 43, "microsecond": 972000, "isocalendar": [2010, 3, 6], "timetuple": [2010, 1, 23, 1, 12, 43, 5, 23, -1], "年": 2010、"エポック": 1264209163.0、"isoformat": "2010-01-23T01:12:43.972000"、"日": 23、"分": 12}、"作者": {"ニックネーム": " test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "test", "date": {"ctime": " Fri Jan 22 22:32:13 2010", "hour": 22, "isoweekday": 5, "month": 1, "second": 13, "microsecond": 659000, "isocalendar": [2010, 3, 5]、「タイムタプル」:[2010、1、22、22、32、13、4、22、-1]、「年」:2010、「エポック」: 1264199533.0、「アイソフォーマット」: 「2010-01-22T22:32:13.659000」、「日」: 22、「分」: 32}、「作成者」: {"ニックネーム": "test@example .com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "", "date": {"ctime": "Fri Jan 22 22 :29:49 2010"、"時": 22、"isoweekday": 5、"月": 1、"秒": 49、"マイクロ秒": 358000、"isocalendar": [2010, 3, 5]," timetuple": [2010, 1, 22, 22, 29, 49, 4, 22, -1], "年": 2010, "エポック": 1264199389.0, "isoformat": "2010-01-22T22:29:49.358000 "、"日": 22、"分": 29}、"作成者": {"ニックネーム": "test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "ああ、動く!\r\n" , "date": {"ctime": "Fri Jan 22 2010 22:29:22", "hour": 22, "isoweekday": 5, "month": 1, "second": 22, "microsecond": 995000、"isocalendar": [2010, 3, 5]、"timetuple": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "year": 2010, "epoch": 1264199362.0 , "isoformat": "2010-01-22T22:29:22.995000", "日": 22, "分": 29}, "作成者": {"ニックネーム": "test@example.com", "メール" : "test@example.com", "auth_domain": "gmail.com"}}]test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "ああ、動く!\r\n", "date" : {"ctime": "Fri Jan 22 2010 22:29:22", "hour": 22, "isoweekday": 5, "month": 1, "second": 22, "microsecond": 995000, "isocalendar ": [2010, 3, 5], "timetuple": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "年": 2010, "エポック": 1264199362.0, "isoformat" : "2010-01-22T22:29:22.995000", "日": 22, "分": 29}, "作成者": {"ニックネーム": "test@example.com", "メール": "test@ example.com", "auth_domain": "gmail.com"}}]test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "ああ、動く!\r\n", "date" : {"ctime": "Fri Jan 22 2010 22:29:22", "hour": 22, "isoweekday": 5, "month": 1, "second": 22, "microsecond": 995000, "isocalendar ": [2010, 3, 5], "timetuple": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "年": 2010, "エポック": 1264199362.0, "isoformat" : "2010-01-22T22:29:22.995000", "日": 22, "分": 29}, "作成者": {"ニックネーム": "test@example.com", "メール": "test@ example.com", "auth_domain": "gmail.com"}}]test@example.com", "auth_domain": "gmail.com"}}, {"content": "ああ、うまくいきました!\r\n", "date": {"ctime": "Fri Jan 22 22: 29:22 2010"、"時": 22、"isoweekday": 5、"月": 1、"秒": 22、"マイクロ秒": 995000、"isocalendar": [2010, 3, 5], "timetuple ": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "年": 2010, "エポック": 1264199362.0, "isoformat": "2010-01-22T22:29:22.995000" , "日": 22, "分": 29}, "作成者": {"ニックネーム": "test@example.com", "メール": "test@example.com", "auth_domain": "gmail. com"}}]test@example.com", "auth_domain": "gmail.com"}}, {"content": "ああ、うまくいきました!\r\n", "date": {"ctime": "Fri Jan 22 22: 29:22 2010"、"時": 22、"isoweekday": 5、"月": 1、"秒": 22、"マイクロ秒": 995000、"isocalendar": [2010, 3, 5], "timetuple ": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "年": 2010, "エポック": 1264199362.0, "isoformat": "2010-01-22T22:29:22.995000" , "日": 22, "分": 29}, "作成者": {"ニックネーム": "test@example.com", "メール": "test@example.com", "auth_domain": "gmail. com"}}]: "ああ、うまくいきました!\r\n", "date": {"ctime": "Fri Jan 22 22:29:22 2010", "hour": 22, "isoweekday": 5, "month": 1 , "second": 22, "microsecond": 995000, "isocalendar": [2010, 3, 5], "timetuple": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "年": 2010、"エポック": 1264199362.0、"isoformat": "2010-01-22T22:29:22.995000"、"日": 22、"分": 29}、"作成者": {"ニックネーム": "test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}]: "ああ、うまくいきました!\r\n", "date": {"ctime": "Fri Jan 22 22:29:22 2010", "hour": 22, "isoweekday": 5, "month": 1 , "second": 22, "microsecond": 995000, "isocalendar": [2010, 3, 5], "timetuple": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "年": 2010、"エポック": 1264199362.0、"isoformat": "2010-01-22T22:29:22.995000"、"日": 22、"分": 29}、"作成者": {"ニックネーム": "test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}]second": 22, "microsecond": 995000, "isocalendar": [2010, 3, 5], "timetuple": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "年": 2010, "epoch": 1264199362.0, "isoformat": "2010-01-22T22:29:22.995000", "day": 22, "minute": 29}, "author": {"nickname": "test @example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}]second": 22, "microsecond": 995000, "isocalendar": [2010, 3, 5], "timetuple": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "年": 2010, "epoch": 1264199362.0, "isoformat": "2010-01-22T22:29:22.995000", "day": 22, "minute": 29}, "author": {"nickname": "test @example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}]test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}]test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}]

于 2010-01-23T22:51:12.123 に答える
10

Jader Dias によって提供された例は、微調整した後、私の懸念に対してうまく機能します。循環参照が含まれているため、encode メソッドを削除します。調整されたクラスは次のようになります。

import datetime  
import time 

from google.appengine.api import users 
from google.appengine.ext import db 
from django.utils import simplejson  


class GqlEncoder(simplejson.JSONEncoder): 

    """Extends JSONEncoder to add support for GQL results and properties. 

    Adds support to simplejson JSONEncoders for GQL results and properties by 
    overriding JSONEncoder's default method. 
    """ 

    # TODO Improve coverage for all of App Engine's Property types. 

    def default(self, obj): 

        """Tests the input object, obj, to encode as JSON.""" 

        if hasattr(obj, '__json__'): 
            return getattr(obj, '__json__')() 

        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 
        
        elif isinstance(obj, datetime.datetime): 
            output = {} 
            fields = ['day', 'hour', 'microsecond', 'minute', 'month', 'second', 'year'] 
            methods = ['ctime', 'isocalendar', 'isoformat', 'isoweekday', 'timetuple'] 
            for field in fields: 
                output[field] = getattr(obj, field) 
            for method in methods: 
                output[method] = getattr(obj, method)() 
            output['epoch'] = time.mktime(obj.timetuple()) 
            return output

        elif isinstance(obj, datetime.date): 
            output = {} 
            fields = ['year', 'month', 'day'] 
            methods = ['ctime', 'isocalendar', 'isoformat', 'isoweekday', 'timetuple'] 
            for field in fields: 
                output[field] = getattr(obj, field) 
            for method in methods: 
                output[method] = getattr(obj, method)() 
            output['epoch'] = time.mktime(obj.timetuple()) 
            return output 
        
        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) 

このクラスをというファイルに保存したのでutils.py、必要に応じて次を使用してインポートします

import utils

utils.GqlEncoder().encode(results)次に、たとえば次のように呼び出します。

query = User.all()
results = query.fetch(10)
            
self.response.headers['Content-Type'] = "text/plain" # Alt. application/json
self.response.out.write( utils.GqlEncoder().encode(results) )

結果は次のようになります (読みやすくするために改行を追加しました)。

[
{"date": {"ctime": "Tue Feb 23 10:41:21 2010", "hour": 10, "isoweekday": 2, "month": 2, 
        "second": 21, "microsecond": 495535, "isocalendar": [2010, 8, 2], "timetuple": [2010, 2, 23, 10, 41, 21, 1, 54, -1], 
        "year": 2010, "epoch": 1266921681.0, "isoformat": "2010-02-23T10:41:21.495535", "day": 23, "minute": 41}, 
"claimed_id": "https:\/\/www.google.com\/accounts\/o8\/id?id=abcdefghijklmnopqrstuvxyz", 
"display_name": "Alfred E Neumann", 
"email": null, 
"full_name": "Alfred E Neumann"
}, 
{"date": {"ctime": "Tue Feb 23 11:00:54 2010", "hour": 11, "isoweekday": 2, "month": 2, 
        "second": 54, "microsecond": 805261, "isocalendar": [2010, 8, 2], "timetuple": [2010, 2, 23, 11, 0, 54, 1, 54, -1], 
        "year": 2010, "epoch": 1266922854.0, "isoformat": "2010-02-23T11:00:54.805261", "day": 23, "minute": 0}, 
"claimed_id": "http:\/\/openid.domain.net\/john", 
"display_name": "", 
"email": "jd@domain.net", 
"full_name": "John Doe"
}
]
于 2010-02-25T10:07:40.017 に答える
3

json を使用して、辞書、リスト、int/long、文字列などの基本的な型以外のものをシリアル化することはできません (これは包括的ではありません)。たとえば、次の単純なコマンドでさえ機能しません。

import json
json.dumps(object())

django オブジェクトをシリアライズする場合は、シリアライゼーションに関する django ドキュメントを参照する必要があります。これは独自のライブラリを使用しますが、json をサポートします。

于 2010-01-22T04:07:08.477 に答える
0

適切な解決策が見つからなかったので、JSON シリアライザーではなく、Javascript シリアライザーを独自に作成しました。

from google.appengine.ext import db
from google.appengine.api.datastore_types import *

def dumpStr(obj):
    return "'" + obj + "'"

def dumps(obj):
    if isinstance(obj, str):
        return dumpStr(obj)
    elif obj == None:
        return None
    elif isinstance(obj, list):
        items = [];
        for item in obj:
            items.append(dumps(item))
        return '[' + ','.join(items) + ']'
    elif isinstance(obj, datetime.datetime):
        return "new Date('%s')" % obj.ctime()
    properties = [];
    for property in dir(obj):
        if property[0] != '_':
            value = obj.__getattribute__(property)
            valueClass = str(value.__class__)
            if not(('function' in valueClass) or ('built' in valueClass) or ('method' in valueClass)):
                value = dumps(value)
                if value != None:
                    properties.append("'" + property + "':" + value)
    if len(properties) == 0:
        return str(obj)
    else:
        return '{' + ','.join(properties) + '}'
于 2010-01-23T19:26:18.773 に答える
-1

私が理解できることから-そして私はpythonが初めてです-Googleアプリエンジンを使用すると、モデルオブジェクトを辞書のpythonオブジェクトにシリアル化し、単純なjsonを使用してjson文字列としてダンプすることです-これは私には意味がありません- 誰かが辞書 (ピッケル?) にシリアル化する方法を知っているかもしれません。Google App Engine には、このためのソリューションが組み込まれていないことに感銘を受けません。

于 2010-01-23T22:11:24.513 に答える