Young Young - 1 month ago 18
JSON Question

Google App Engine - JSON Serialization of GeoPt data

I am trying to create an API for my web app but I keep getting an error when trying to load GeoPtProperty to JSON. I tried converting GeoPt data into JSON object but it didn't work.

class Post(ndb.Model):
content = ndb.StringProperty(required = True)
user = ndb.StringProperty()
coords = ndb.GeoPtProperty()

def render(self):
self._render_text = self.content.replace('\n', '<br>')
params = dict(p = self)

return render_str("post.html", **params)

def as_dict(self):
d = {'content': self.content,
'user': self.user,
'coords': self.coords}

return d

class Handler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)

def render_json(self, d):
json_txt = json.dumps(d)
self.response.headers['Content-Type'] = 'application/json; charset=UTF-8'
self.write(json_txt)

class MainPage(Handler):
def get(self):
posts = Post.query(ancestor=post_key()).order(-Post.created)

if self.format == 'json':
self.response.headers['Access-Control-Allow-Origin'] = '*'
return self.render_json([p.as_dict() for p in posts])


Below is the traceback

Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~website/1.396738651304801066/main.py", line 121, in get
return self.render_json([p.as_dict() for p in posts])
File "/base/data/home/apps/s~website/1.396738651304801066/main.py", line 45, in render_json
json_txt = json.dumps(d)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/json/__init__.py", line 243, in dumps
return _default_encoder.encode(obj)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/json/encoder.py", line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/json/encoder.py", line 270, in iterencode
return _iterencode(o, 0)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/json/encoder.py", line 184, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: datastore_types.GeoPt(37.636003000000002, 127.216528) is not JSON serializable


How can I properly receive data in JSON?

Answer

I finally figured it out and will answer my own question. GeoPt data cannot be serialized so it has to be converted into JSON object. When storing GeoPT, you can simply use the below code.

        if coords:
            coords = ndb.GeoPt(lat, lon)
            p.coords = coords
        p.put()

The ndb datastore entity looks like this:

class Post(ndb.Model):
    coords = ndb.GeoPtProperty()

I was able to fetch lat and lon, and convert them into JSON object.

coords = self.coords.lat, self.coords.lon
lat, lon = coords[0], coords[1]
coords = {'latitude': lat, 'longitude': lon}

This did the trick and my app is no longer throwing an error.