【问题标题】:GAE Datastore date is not JSON serializableGAE 数据存储日期不是 JSON 可序列化的
【发布时间】:2015-03-21 15:51:20
【问题描述】:

我正在尝试从应用引擎中的数据存储区发送 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 格式?

Br

【问题讨论】:

    标签: python json google-app-engine


    【解决方案1】:

    我建议不要重新发明轮子,而是在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 列表中,然后您将完全忽略它们!然后所有 消息(来自查询循环)被放入 items 中无限的数字。我有点怀疑这实际上是你想要的——也许你的意思是 for 是:

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

    将响应序列化为“仅最新的 10 条消息”而不是“所有消息 除了最新的 10 条消息”,这就是您的代码所做的。

    因此,如果是这种情况,我建议您使用该模块避免所有“构建items”部分,而只需替换

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

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

    (另请注意,out 部分是旧版工件/hack,用于向后兼容 webapp 的旧版本,最好不要用于新应用程序 - 与您的 Q 没有直接关系,但就像我的相信是您在序列化“查询的其余部分”而不是“最新的 10 条消息”时可能遇到的错误,希望对您有所帮助!-)

    【讨论】:

      【解决方案2】:

      您可以扩展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"}
      

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 2015-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-09
          • 2013-06-09
          相关资源
          最近更新 更多