Christopher
Christopher

Reputation: 345

Google App Engine Datastore Query to JSON with Python

How can I get a JSON Object in python from getting data via Google App Engine Datastore?

I've got model in datastore with following field:

id
key_name
object
userid
created

Now I want to get all objects for one user:

query = Model.all().filter('userid', user.user_id())

How can I create a JSON object from the query so that I can write it?

I want to get the data via AJAX call.

Upvotes: 2

Views: 5346

Answers (3)

xlm
xlm

Reputation: 7614

Not sure if you got the answer you were looking for, but did you mean how to parse the model (entry) data in the Query object directly into a JSON object? (At least that's what I've been searching for).

I wrote this to parse the entries from Query object into a list of JSON objects:

def gql_json_parser(query_obj):
    result = []
    for entry in query_obj:
        result.append(dict([(p, unicode(getattr(entry, p))) for p in entry.properties()]))
    return result

You can have your app respond to AJAX requests by encoding it with simplejson e.g.:

query_data = MyModel.all()
json_query_data = gql_json_parser(query_data)
self.response.headers['Content-Type'] = 'application/json'
self.response.out.write(simplejson.dumps(json_query_data))

Your app will return something like this:

[{'property1': 'value1', 'property2': 'value2'}, ...]

Let me know if this helps!

Upvotes: 8

dminer
dminer

Reputation: 1141

I did the following to convert the google query object to json. I used the logic in jql_json_parser above as well except for the part where everything is converted to unicode. I want to preserve the data-types like integer, floats and null.

import json
class JSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, 'isoformat'): #handles both date and datetime objects
            return obj.isoformat()
        else:
            return json.JSONEncoder.default(self, obj)

class BaseResource(webapp2.RequestHandler):
    def to_json(self, gql_object):
        result = []
        for item in gql_object:
            result.append(dict([(p, getattr(item, p)) for p in item.properties()]))
        return json.dumps(result, cls=JSONEncoder)

Now you can subclass BaseResource and call self.to_json on the gql_object

Upvotes: 0

Aaron Watters
Aaron Watters

Reputation: 2846

If I understood you correctly I have implemented a system that works something like this. It sounds like you want to store an arbitrary JSON object in a GAE datastore model. To do this you need to encode the JSON into a string of some sort on the way into the database and decode it from a string into a python datastructure on the way out. You will need to use a JSON coder/decoder to do this. I think the GAE infrastructure includes one. For example you could use a "wrapper class" to handle the encoding/decoding. Something along these lines...

class InnerClass(db.Model):
    jsonText = db.TextProperty()
    def parse(self):
        return OuterClass(self)

class Wrapper:
    def __init__(self, storage=None):
        self.storage = storage
        self.json = None
        if storage is not None:
            self.json = fromJsonString(storage.jsonText)
    def put(self):
        jsonText  = ToJsonString(self.json)
        if self.storage is None:
            self.storage = InnerClass()
        self.storage.jsonText = jsonText
        self.storage.put()

Then always operate on parsed wrapper objects instead of the inner class

def getall():
    all = db.GqlQuery("SELECT * FROM InnerClass")
    for x in all:
        yield x.parse()

(untested). See datastoreview.py for some model implementations that work like this.

Upvotes: 1

Related Questions