将ndb.Model序列化为JSON的替代方案
我有一个ndb.Model要转换为JSON将ndb.Model序列化为JSON的替代方案,json,python-2.7,google-app-engine,google-cloud-datastore,app-engine-ndb,Json,Python 2.7,Google App Engine,Google Cloud Datastore,App Engine Ndb,我有一个ndb.Model要转换为JSON class Users(ndb.Model): username = ndb.StringProperty(indexed=True) password= ndb.StringProperty(indexed=True) created_at = ndb.DateTimeProperty(auto_now_add=True) user = Users.query(Users.username==username).get()
class Users(ndb.Model):
username = ndb.StringProperty(indexed=True)
password= ndb.StringProperty(indexed=True)
created_at = ndb.DateTimeProperty(auto_now_add=True)
user = Users.query(Users.username==username).get()
rv = json.dumps(user.to_dict())
print(rv)
它抛出以下错误:
TypeError: datetime.datetime(2013, 11, 24, 3, 40, 15) is not JSON serializable
这里的大多数解决方案都是针对db.Model的,已经相当过时了
sdk版本1.9.10您需要一个自定义的“到JSON”转换器,该转换器处理JSON本机不支持的格式
我正在使用类似以下代码的东西来处理大多数情况
def to_json(self, o):
if isinstance(o, list):
return [self.to_json(l) for l in o]
if isinstance(o, dict):
x = {}
for l in o:
x[l] = self.to_json(o[l])
return x
if isinstance(o, datetime.datetime):
return o.isoformat()
if isinstance(o, ndb.GeoPt):
return {'lat': o.lat, 'lon': o.lon}
if isinstance(o, ndb.Key):
return o.urlsafe()
if isinstance(o, ndb.Model):
dct = o.to_dict()
dct['id'] = o.key.id()
return self.to_json(dct)
return o
因此,在我的例子中,我还负责一些其他事情,如GeoPt,并为所有ndb模型添加一个ID字段。但对于您的例子,您需要的是:
if isinstance(o, datetime.datetime):
return o.isoformat()
但我猜(不是很确定)您也会得到一个关键错误,所以您还需要
if isinstance(o, ndb.Key):
return o.urlsafe()
如果您不需要在处创建字段,您可以简单地将其排除在外,如
rv = json.dumps(user.to_dict(exclude=['created_at']))
可以扩展属性类以处理特殊情况。它适用于任何属性类型
from google.appengine.ext import ndb
class DateTimeProperty(ndb.DateTimeProperty):
# Override to allow JSON serialization
def _get_for_dict(self, entity):
value = super(DateTimeProperty, self)._get_for_dict(entity);
return value.isoformat()
然后在您的模型中使用它:
class Users(ndb.Model):
username = ndb.StringProperty(indexed=True)
password= ndb.StringProperty(indexed=True)
created_at = DateTimeProperty(auto_now_add=True)
和到_dict()
user = Users.query(Users.username==username).get()
user.to_dict()
另一个可能的解决方案——灵感来自答案——是在用户
类中重写到_dict()
:
class User(ndb.Model):
username = ndb.StringProperty(indexed=True)
password = ndb.StringProperty(indexed=False)
created_at = DateTimeProperty(auto_now_add=True)
def to_dict(self):
result = super(User, self).to_dict()
result['created_at'] = self.created_at.isoformat()
return result
无关注释:如果您只需要一个结果,您可以使用.get()
而不是.fetch(1)
,这样您就不会得到一个元素的列表,也就是说,以后您可以使用user.to dict()
而不是user[0]。to dict()
。仍然会引发错误:TypeError:datetime.datetime(2013,11,24,3,40,15)JSON不可序列化,我使用python2.7和适用于linux 1.9.10的gae sdk。您如何使用它?与json.dumps(user.to_dict())
不同,您需要类似于json.dumps(self.to_json(user))
。json.dumps有一个参数'default',可以为其他不可变量类型调用函数,允许您选择json中包含的属性与序列化分开。这无疑是最简单的解决方案。谢谢