GAE NDB 结构化列表转为 Json

1 投票
1 回答
1413 浏览
提问于 2025-04-18 01:30

我最近从ext.db切换到了新的NDB,但遇到了一些困难。

我想把一个结构化的列表转换成Json格式,这样我就可以发送给iPhone应用程序。但是我遇到了“不是JSON可序列化”的错误。我希望把用户喜欢的所有水果都转换成Json。如果一个用户喜欢苹果、橙子和草莓,那么在下面代码中的favorites字段里应该包含这三种水果,以及它们的分数和评论。

我知道有to_dict和jsonProperty这两个东西,但我不知道怎么用。

以下是我现在的代码:

class FavFruits(ndb.Model):
    fruit    = ndb.StringProperty()
    score    = ndb.IntegerProperty()
    comment  = ndb.TextProperty()

 class UserProfile(ndb.Model):
    uid            = ndb.StringProperty(required=True)
    favFruits      = ndb.StructuredProperty(FavFruits, repeated=True)

 @classmethod
 def makeJsonPackage(cls, uid):
      fruitList = UserProfile.query(UserProfile.uid == uid).get()
            entry = {}
            entry["uid"]           = fruitList.uid
            entry["favorites"]     = fruitList.favFruits
            return (entry)

 # down stream of the code
 jsonData = UserProfile.makeJsonPackage(uid)
 self.response.write(json.dumps(jsonData))

这个代码不行……问题出在entry["favorites"] = fruitList.favFruits,因为我在把结构化列表转换成Json数据时遇到了问题。

我的目标是发送整个favFruits的列表(多个水果)。我想保留结构化列表,因为当用户请求“苹果”时,我想查询数据,这样我就可以显示这个水果(苹果)及其相关的分数和评论。

任何帮助都将非常感谢。

1 个回答

2

根据 AppEngine 让 ndb 模型支持 JSON 序列化文档,下面的代码应该可以正常工作。

这个方法会返回一个字典,里面包含模型的属性值。对于结构化属性(StructuredProperty)和本地结构化属性(LocalStructuredProperty),它们的值会被递归地转换成字典。

@classmethod
def makeJsonPackage(cls, uid):
    fruitList = UserProfile.query(UserProfile.uid == uid).get()
    return json.dumps(fruitList.to_dict())

更新1

userPorfile = UserProfile.query(UserProfile.uid == uid).get()
return json.dumps([k.to_dict() for k in userProfile.favFruits])

额外信息:使用 Endpoints

因为你想把 AppEngine 用作移动应用的后端 API 服务器,所以首先要看看 Endpoints API。这个 API 是专门为这种用途设计的。

https://developers.google.com/appengine/docs/java/endpoints/

基于 Endpoints,还有一个谷歌支持的包叫做 Endpoints Proto Datastore API。这个包提供了 ndb 模型和 Endpoints 之间更直接的连接。一开始可能会觉得有点难,但一旦你明白它是怎么工作的,就会发现它非常强大,可以节省很多时间。

http://endpoints-proto-datastore.appspot.com/

更新 2:

编辑1: 我为 ndb 模型写了一个 RESTFul API 生成器。

# generate restful api in one line
BigDataLab = EndpointRestBuilder(GPCode).build(
    api_name="BigDataLab",
    name="bigdatalab",
    version="v1",
    description="My Little Api"
)

代码库: https://github.com/Tagtoo/endpoints-proto-datastore-rest

撰写回答