【问题标题】:AppEngine Making ndb models json serializableAppEngine 使 ndb 模型 json 可序列化
【发布时间】:2012-10-29 23:12:39
【问题描述】:

我们有一个 ndb 模型,我们想让 json 可序列化。这些模型非常简单:

class Pasta(ndb.Model):
   name = ndb.StringProperty()
   type = ndb.StringProperty()
   comments = ndb.JsonProperty()

然后在处理程序方面,我们想做一些类似的事情:

json.dumps(Pasta.query(Pasta.name=="Ravioli").fetch()) 并将其返回给客户端,但它不断抛出 json 解析错误,因为 Pasta 类不是 json 可序列化的。所以,问题是,我们必须实现__str____repr__ 还是有更好的方法来实现它?

【问题讨论】:

  • 追根究底。谢谢你。当我搜索这些问题时,我几乎找不到这些问题。
  • NP。它适用于 DB,但转换应该没什么大不了的。

标签: python google-app-engine


【解决方案1】:

ndb.Model 实例有一个 to_dict() 函数: https://developers.google.com/appengine/docs/python/ndb/modelclass#Model_to_dict

最简单的方法是:

json.dumps([p.to_dict() for p in Pasta.query(Pasta.name == "Ravioli").fetch()])

【讨论】:

  • 可能值得注意的是,to_dict 不包括模型中的key。所以你可能希望做类似json.dumps([dict(p.to_dict(), **dict(id=p.key.id())) for p in ...
  • 为避免日期时间错误,请使用json.dumps(..., default=str)
【解决方案2】:

我不相信它已记录在案,但对于现有的ext.db 模型,您可以使用db.to_dict()(请参阅here)。

注意db.ReferencePropertydb.DateTimeProperty,因为当您调用json.dumps() 时它们会抛出错误。快速解决方案是自定义 JSONEncoder:

from datetime import datetime, date, time
from google.appengine.ext import db

import json

class JSONEncoder(json.JSONEncoder):

    def default(self, o):
        # If this is a key, you might want to grab the actual model.
        if isinstance(o, db.Key):
            o = db.get(o)

        if isinstance(o, db.Model):
            return db.to_dict(o)
        elif isinstance(o, (datetime, date, time)):
            return str(o)  # Or whatever other date format you're OK with...

然后用这个编码:

JSONEncoder().encode(YourModel.all().fetch())

【讨论】:

    【解决方案3】:

    或者你可以像下面这样向模型添加一个计算属性:

    class Taxes(ndb.Model):
        name = ndb.StringProperty()
        id = ndb.ComputedProperty(lambda self: self.key.id())
    

    然后在您的 get 方法中只需调用 to_dict 即可获得 id

    rows = [row.to_dict() for row in Taxes.query()]
    self.response.write(json.dumps(rows))
    

    【讨论】:

      【解决方案4】:

      如果有一个 ndb.KeyProperty 引用不同的模型,你可以很好地覆盖字典方法,如下所示

      def to_dict(self):
              result = super(Point, self).to_dict()
              result['x']=self.x.get().to_dict()
              result['y']=self.y.get().to_dict()
              return result
      

      如果 ndb.KeyProperty 是一个列表(重复设置为 True),请使用以下方法使用 get_multi 获取引用的模型

      def to_dict(self):
             result = super(Figure, self).to_dict()
             result['points']=[p.to_dict() for p in ndb.get_multi(self.points)]
             return result 
      

      【讨论】:

        【解决方案5】:

        如果有一个 ndb.KeyProperty 引用不同的模型,你可以很好地覆盖字典方法,如下所示

        def to_dict(self):
                result = super(Point, self).to_dict()
                result['x']=self.x.get().to_dict()
                result['y']=self.y.get().to_dict()
                return result
        

        如果 ndb.KeyProperty 是一个列表(重复设置为 True),并且如果您也打算序列化引用的模型,请使用以下方法使用 get_multi 获取引用的模型

        def to_dict(self):
               result = super(Figure, self).to_dict()
               result['points']=[p.to_dict() for p in ndb.get_multi(self.points)]
               return result 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-27
          • 2019-12-27
          • 1970-01-01
          • 2013-03-04
          • 2011-01-16
          • 1970-01-01
          相关资源
          最近更新 更多