将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()

我有一个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()
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中包含的属性与序列化分开。这无疑是最简单的解决方案。谢谢