We have an ndb model that we would like to make json serializable. The models are fairly simple along the lines of:
class Pasta(ndb.Model):
name = ndb.StringProperty()
type = ndb.StringProperty()
comments = ndb.JsonProperty()
Then on the handler side we would like to do something along the lines of:
json.dumps(Pasta.query(Pasta.name=="Ravioli").fetch())
and return it to the client, but it keeps throwing json parse errors since the class Pasta is not json serializable. So, the question is, do we have to implement __str__
or __repr__
or is there a niftier way to do it?
ndb.Model
instances have a to_dict()
function:
https://developers.google.com/appengine/docs/python/ndb/modelclass#Model_to_dict
the simplest way is:
json.dumps([p.to_dict() for p in Pasta.query(Pasta.name == "Ravioli").fetch()])
I don't believe it's documented, but for existing ext.db
Models, you can use db.to_dict()
(see here).
Be careful though with db.ReferenceProperty
's and db.DateTimeProperty
's as they will throw errors when you call json.dumps()
. The quick solution is a custom 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...
Then to encode with this:
JSONEncoder().encode(YourModel.all().fetch())
Or you can just add a computed property to the model like below:
class Taxes(ndb.Model):
name = ndb.StringProperty()
id = ndb.ComputedProperty(lambda self: self.key.id())
then in your get method just call to_dict and you will get the id
rows = [row.to_dict() for row in Taxes.query()]
self.response.write(json.dumps(rows))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With