Google app engine 子类化db.TextProperty以将python dict存储为JSON并将默认编码设置为除ASCII以外的任何内容

Google app engine 子类化db.TextProperty以将python dict存储为JSON并将默认编码设置为除ASCII以外的任何内容,google-app-engine,unicode,utf-8,google-cloud-datastore,Google App Engine,Unicode,Utf 8,Google Cloud Datastore,使用GoogleAppEngine(python SDK),我创建了一个自定义JSONProperty(),作为db.TextProperty()的子类。我的目标是将python dict动态存储为JSON并轻松检索。我遵循了通过Google找到的各种示例,设置自定义属性类和方法非常简单 但是,我的一些dict值(字符串)是用utf-8编码的。将模型保存到数据存储中时,我遇到了一个可怕的Unicode错误(对于数据存储文本属性,默认编码为ASCII)。子类化db.BlobProperty无法解决

使用GoogleAppEngine(python SDK),我创建了一个自定义JSONProperty(),作为db.TextProperty()的子类。我的目标是将python dict动态存储为JSON并轻松检索。我遵循了通过Google找到的各种示例,设置自定义属性类和方法非常简单

但是,我的一些dict值(字符串)是用utf-8编码的。将模型保存到数据存储中时,我遇到了一个可怕的Unicode错误(对于数据存储文本属性,默认编码为ASCII)。子类化db.BlobProperty无法解决此问题

基本上,我的代码执行以下操作:将资源实体存储到数据存储中(URL作为StringProperty,POST/GET有效负载作为JSONProperty存储在dict中),稍后获取它们(不包括代码)。我选择不使用pickle来存储有效负载,因为我是一个JSON怪胎,无法存储对象

自定义JSONProperty:

class JSONProperty(db.TextProperty):
    def get_value_for_datastore(self, model_instance):
        value = super(JSONProperty, self).get_value_for_datastore(model_instance)
        return json.dumps(value)

    def make_value_from_datastore(self, value):
        if value is None:
            return {}
        if isinstance(value, basestring):
            return json.loads(value)
        return value
将模型放入数据存储:

res = Resource()
res.init_payloads()
res.url = "http://www.somesite.com/someform/"
res.param = { 'name': "SomeField", 'default': u"éàôfoobarç" }
res.put()
这将抛出与ASCII编码相关的UnicodeDecodeError。也许值得注意的是,我只在生产服务器上(每次)收到这个错误。我在dev上使用python2.5.2

回溯(最近一次呼叫最后一次): 文件“/base/data/home/apps/delpythian/1.350065314722833389/core/handlers/ResetHandler.py”,第68行,在 return resu one.put() 文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/ext/db/init.py”,第984行,输入 返回datastore.Put(self.\u实体,config=config) 文件“/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py”,第455行,输入 return\u GetConnection().async\u put(配置、实体、额外的\u钩子)。get\u result() 文件“/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py”,第1219行,异步输入 对于pbsgen中的pbs: 文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/datastore/datastore\u rpc.py”,第1070行,位于生成pb列表中 pb=值_至_pb(值) 文件“/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py”,第239行,在实体_到_pb中 返回实体。_ToPb() 文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/api/datastore.py”,第841行,在 属性=数据存储\类型.ToPropertyPb(名称、值) ToPropertyPb中的文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/api/datastore\u types.py”,第1672行 pbvalue=pack_prop(name,v,pb.mutable_value()) PackString中的文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/api/datastore\u types.py”,第1485行 pbvalue.set_stringvalue(unicode(value).encode('utf-8')) UnicodeDecodeError:“ascii”编解码器无法解码位置32中的字节0xc3:序号不在范围内(128)

我的问题是:有没有一种方法可以将db.TextProperty()类划分为子类并设置/实施自定义编码?还是我做错了什么?我尽量避免使用str(),并遵循“早解码,处处使用Unicode,晚编码”的规则


更新:添加了代码和stacktrace。

下面是一个将unicode字符串从字典移动到序列化JSON字符串再移动到TextProperty的最小示例:

class Thing(db.Model):
  json = db.TextProperty()

class MainHandler(webapp.RequestHandler):
  def get(self):
    data = {'word': u"r\xe9sum\xe9"}
    json = simplejson.dumps(data, ensure_ascii=False)
    Thing(json=json).put()
这对我在开发和生产中都很有用。

看看这行: PackString pbvalue.set_stringvalue(unicode(value).encode('utf-8'))UnicodeDecodeError:'ascii'

似乎appengine希望所有字符串值都是unicode。调用unicode(值)没有指定编码,因此可能默认为ascii,除非值已经是unicode,例如:

>>> u = u"ąęćźż"
>>> s = u.encode('utf-8')
>>> unicode(u) # fine
>>> unicode(s, 'utf-8') # fine
>>> unicode(s) # blows up (try's ascii) (on my interpreter)
json.dumps将编码一个utf-8字符串(默认情况下),这就是unicode无法处理它的原因

试试这个:

>>> return unicode(json.dumps(...), 'utf-8')
你应该没事的

至于为什么阿彭金爆炸了,而你的翻译还好,我猜可能是当地人
设置,docstring for unicode表示默认为当前默认编码,您的默认编码为utf-8,gae的默认编码为ascii。

请添加代码示例和堆栈跟踪。特别是,我想确认UnicodeError是在您尝试存储TextProperty时发生的,而不是在您尝试将Python字典序列化为JSON时发生的。更新了问题,添加了代码和堆栈跟踪。您好,谢谢,我没有考虑查看dumps()方法。然而,我仍然在prod上获得相同的堆栈跟踪。在dev上运行良好。这令人困惑!