使用時
from django.utils import simplejson
それから派生しdb.Model
た型のオブジェクトでは、例外がスローされます。これを回避する方法は?
使用時
from django.utils import simplejson
それから派生しdb.Model
た型のオブジェクトでは、例外がスローされます。これを回避する方法は?
わかりました-私の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"}}]
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"
}
]
json を使用して、辞書、リスト、int/long、文字列などの基本的な型以外のものをシリアル化することはできません (これは包括的ではありません)。たとえば、次の単純なコマンドでさえ機能しません。
import json
json.dumps(object())
django オブジェクトをシリアライズする場合は、シリアライゼーションに関する django ドキュメントを参照する必要があります。これは独自のライブラリを使用しますが、json をサポートします。
適切な解決策が見つからなかったので、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) + '}'
私が理解できることから-そして私はpythonが初めてです-Googleアプリエンジンを使用すると、モデルオブジェクトを辞書のpythonオブジェクトにシリアル化し、単純なjsonを使用してjson文字列としてダンプすることです-これは私には意味がありません- 誰かが辞書 (ピッケル?) にシリアル化する方法を知っているかもしれません。Google App Engine には、このためのソリューションが組み込まれていないことに感銘を受けません。