GAE数据存储日期不是JSON可序列化的

时间:2015-03-21 15:51:21

标签: python json google-app-engine

我试图从应用引擎中的数据存储区发送10条最新帖子。

这是数据库:

class Author(ndb.Model):
    """Sub model for representing an author."""
    identity = ndb.StringProperty(indexed=False)
    email = ndb.StringProperty(indexed=True)

class Message(ndb.Model):
    """A main model for representing an individual Message entry."""
    author = ndb.StructuredProperty(Author)
    content = ndb.StringProperty(indexed=False)
    date = ndb.DateTimeProperty(auto_now_add=True)

这是代码:

class Query(webapp2.RequestHandler):
    def post(self):
        message_name = self.request.get('db_name',
                                         DEFAULT_KEY)
        message_query = Message.query(ancestor=db_key(
                                      message_name)).order(-Message.date)
        messages = message_query.fetch(10)

        items = [] 

        for message in message_query:
            items.append({'id': message.author.identity, 
                          'email':message.author.email,
                          'content':message.content,
                          'date':message.date})    


        self.response.headers['Content-Type'] = 'application/json'   
        self.response.out.write(json.dumps(items))

错误信息:

TypeError: datetime.datetime(2015, 3, 21, 15, 43, 58, 248650) is not JSON serializable

为什么不能让JSON返回该格式的日期? 我如何将其重新格式化为正确的JSON格式?

3 个答案:

答案 0 :(得分:5)

我建议不要重新发明轮子,而是建议在https://gist.github.com/erichiggins/8969259安装和使用ndb_json.py模块 - 它代表你强有力地优雅地处理各种潜在的陷阱和陷阱。然后,ndb_json.dumps就是你所需要的。

请注意,您发布的代码中有一个特殊的异常......:

    message_query = Message.query(ancestor=db_key(
                                  message_name)).order(-Message.date)
    messages = message_query.fetch(10)

    items = [] 

    for message in message_query:
        items.append(...)

这会将最新的10条消息提取到messages列表中,然后您完全忽略它!然后所有较旧的消息(来自查询的循环)都会被放入{{ 1}}无限数字。我怀疑这实际上是你想要的 - 也许你的意思是items

for

序列化到响应"只是最新的10条消息"而不是"所有消息除了最新的10"这是你的代码所做的。

所以,如果是这种情况,我建议您使用模块避免 for message in messages: items.append(...) "建立items"部分,只需替换

self.response.out.write(json.dumps(items))

self.response.write(ndb_json.dumps(messages))

(另请注意,out部分是遗留工件/黑客,用于向后兼容古代版本的webapp,最好不在新应用中使用 - 与您的Q没有直接关系,但只是就像我认为的那样,你可能会在序列化"其余的查询"而不是"最新的10条消息"中出现的错误,希望对你有所帮助! - )

答案 1 :(得分:1)

JSON对datetime对象一无所知。这取决于您想要的时间以及以后的时间。我建议你将它转换为unix时间戳,这只是一个整数,因此是JSON可序列化的。

这是一篇文章,其中描述了所有python版本的datetime对象到整数的转换:Converting datetime.date to UTC timestamp in Python

答案 2 :(得分:1)

您可以扩展JSONEncoder类来处理任何对象类型,如下所示:

from datetime import datetime

import json

class MyJsonEncoder(json.JSONEncoder):
   def default(self, obj):
      if isinstance(obj, datetime):
         # format however you like/need
         return obj.strftime("%Y-%m-%d")
      # pass any other unknown types to the base class handler, probably
      # to raise a TypeError.   
      return json.JSONEncoder.default(self, obj)


objDict = {"str":"foo", "int":212, "date":datetime.today()}

print json.dumps(objDict, cls=MyJsonEncoder)

{"int": 212, "date": "2015-03-21", "str": "foo"}