google app engine - Subclassing db.TextProperty for storing python dict as JSON and setting default encoding to anything but ASCII -


using google app engine (python sdk), created custom jsonproperty() subclass of db.textproperty(). goal store python dict on fly json , retrieve easily. followed various examples found via google , setting custom property class , methods pretty easy.

however, of dict values (strings) encoded in utf-8. when saving model datastore, dreaded unicode error (for datastore text property default encoding ascii). subclassing db.blobproperty didn't solve issue.

basically, code following thing : store resource entities datastore (with url stringproperty , post/get payloads stored in dict jsonproperty), fetch them later (code not included). choose not use pickle storing payloads because i'm json freak , have no use storing objects.

custom 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 none:             return {}         if isinstance(value, basestring):             return json.loads(value)         return value 

putting model datastore :

res = resource() res.init_payloads() res.url = "http://www.somesite.com/someform/" res.param = { 'name': "somefield", 'default': u"éàôfoobarç" } res.put() 

this throw unicodedecodeerror related ascii encoding. maybe it's worth noting error (everytime) on production server. i'm using python 2.5.2 on dev.

traceback (most recent call last): file "/base/data/home/apps/delpythian/1.350065314722833389/core/handlers/resethandler.py", line 68, in _res_one return res_one.put() file "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/init.py", line 984, in put return datastore.put(self._entity, config=config) file "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 455, in put return _getconnection().async_put(config, entities, extra_hook).get_result() file "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1219, in async_put pbs in pbsgen: file "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1070, in __generate_pb_lists pb = value_to_pb(value) file "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 239, in entity_to_pb return entity._topb() file "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 841, in _topb properties = datastore_types.topropertypb(name, values) file "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore_types.py", line 1672, in topropertypb pbvalue = pack_prop(name, v, pb.mutable_value()) file "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore_types.py", line 1485, in packstring pbvalue.set_stringvalue(unicode(value).encode('utf-8')) unicodedecodeerror: 'ascii' codec can't decode byte 0xc3 in position 32: ordinal not in range(128)

my question following : there way subclass db.textproperty() class , set/enforce custom encoding ? or doing wrong ? try avoid using str() , follow "decode early, unicode everywhere, encode late" rule.

update : added code , stacktrace.

here's minimal example of moving unicode string dictionary serialized json string 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() 

this works me in both dev , prod.


Comments