6
@route('/locations', method='GET')
def get_location():
    entity = db['locations'].find({'coordinate2d': {'$near': [37.871593, -122.272747]}}).limit(3)
    if not entity:
        abort(404, 'No nearby locations')
    return entity

The response for the above portion of code is:

Error 500: Internal Server Error

Sorry, the requested URL 'http://localhost:8080/locations' caused an error:

Unsupported response type: <type 'dict'>

How can I grab that information from mongo as a type Bottle can return as JSON?

james_womack
  • 10,028
  • 6
  • 55
  • 74
  • Have you tried decomposing the problem, i.e. replacing `db.find` call with a simple dictionary literal? If it works that way, the problem must be Mongo-related. Is it doesn't, it's Bottle-related. – Helgi Feb 23 '12 at 14:35
  • @Helgi I have, Bottle of course works with a regular dictionary literal. It can't handle MongoDB ObjectId's though. – james_womack Feb 23 '12 at 22:46

3 Answers3

3

I got this error when I was trying to return a python list. I assumed it would translate into JSON, but it didn't. It made it to the line in bottle.py where it would handle iterables and found the first dict in the list and threw the error above.

To get around this, I simply embedded my list inside a dict.

return {'response': []}
Daniel Watrous
  • 3,467
  • 2
  • 36
  • 48
  • 1
    This is intentional. See this question and the answer for more info: http://stackoverflow.com/questions/12293979/how-do-i-return-a-json-array-with-bottle – Peter Apr 13 '17 at 08:47
2

The complete solution was a combination of transforming the db cursor to a list, manually setting the response type + custom encoding the return value

@route('/locations/:lat/:lng', method='GET')
def get_location(lat,lng):
    response.content_type = 'application/json'
    objdb = db.locations.find({'coordinate2d': {'$near': [lat,lng]}}, {'coordinate2d':bool(1)}).skip(0).limit(3)
    entries = [entry for entry in objdb]
    return MongoEncoder().encode(entries)

In my case, produces this:

[
    {
        "_id": "4f4201bb7e720d1dca000005",
        "coordinate2d": [
            33.02032100000006,
            -117.19483074631853
        ]
    },
    {
        "_id": "4f4201587e720d1dca000002",
        "coordinate2d": [
            33.158092999999994,
            -117.350594
        ]
    },
    {
        "_id": "4f42018b7e720d1dca000003",
        "coordinate2d": [
            33.195870000000006,
            -117.379483
        ]
    }
]
james_womack
  • 10,028
  • 6
  • 55
  • 74
  • This was great help. I was encountering a similar problem, but had issues since I did not know where MongoEncoder came from. **Simply returning entries did the trick for me.** – Hectron Jun 05 '13 at 20:57
1

As per the doc mention on bottle http://bottlepy.org/docs/dev/ you have to return the string from the @route decorator. You have to return the template with data or string.

If you want to generate the json then you have to change the Content-Type.

Dictionaries

As mentioned above, Python dictionaries (or subclasses thereof) are automatically transformed into JSON strings and returned to the browser with the Content-Type header set to application/json. This makes it easy to implement json-based APIs. Data formats other than json are supported too. See the tutorial-output-filter to learn more.

http://bottlepy.org/docs/dev/tutorial.html?highlight=json#generating-content

Community
  • 1
  • 1
Nilesh
  • 20,521
  • 16
  • 92
  • 148
  • I am returning a dictionary and Bottle returns an error: Unsupported response type: Also, returning a string from @route makes no difference. – james_womack Feb 21 '12 at 12:12
  • have you set the content type ? – Nilesh Feb 21 '12 at 12:36
  • There's an error—setting the content-type merely prints out the error HTML as as plain text. The problem is I'm using geospatial with Mongo. The bottle docs do not cover that. – james_womack Feb 21 '12 at 12:38