Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AppEngine Making ndb models json serializable

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?

like image 484
rdodev Avatar asked Nov 09 '12 15:11

rdodev


3 Answers

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()])
like image 148
aschmid00 Avatar answered Nov 13 '22 15:11

aschmid00


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())
like image 10
JJ Geewax Avatar answered Nov 13 '22 15:11

JJ Geewax


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))
like image 1
Sarfaraz Farooqui Avatar answered Nov 13 '22 15:11

Sarfaraz Farooqui