Flask Jsonify mongoengine query
Asked Answered
C

3

6

I have method like this , and want to return as Json , but it writes that Posts object is not Json serializable :S

def show_results_async(text):
   query  =  { '$or':[{'title':{'$regex':text}},{'author':{'$regex':text}} ]}
   posts = Posts.objects(__raw__=(query))
   return jsonify(result = posts)
Casto answered 22/12, 2012 at 13:10 Comment(1)
why is it __raw__=(query)? did you mean __raw__=(query,) or __raw__=query?Disadvantage
G
5

tl,dr: There is no built-in function that'll convert a MongoEngine document to JSON. So you'll need to write your own.

In views.py:

def show_results_async(text):
   query  =  { '$or':[{'title':{'$regex':text}},{'author':{'$regex':text}} ]}
   posts = Posts.objects(__raw__=(query))
   return jsonify(result=posts.to_dict())

In post.py, add:

def to_dict(self):
   return helper.mongo_to_dict(self)

In helper.py:

def mongo_to_dict(obj):
    return_data = []

    if isinstance(obj, Document):
        return_data.append(("id",str(obj.id)))

    for field_name in obj._fields:

        if field_name in ("id",):
            continue

        data = obj._data[field_name]

        if isinstance(obj._fields[field_name], DateTimeField):
            return_data.append((field_name, str(data.isoformat())))
        elif isinstance(obj._fields[field_name], StringField):
            return_data.append((field_name, str(data)))
        elif isinstance(obj._fields[field_name], FloatField):
            return_data.append((field_name, float(data)))
        elif isinstance(obj._fields[field_name], IntField):
            return_data.append((field_name, int(data)))
        elif isinstance(obj._fields[field_name], ListField):
            return_data.append((field_name, data))
        elif isinstance(obj._fields[field_name], EmbeddedDocumentField):
            return_data.append((field_name, mongo_to_dict(data)))

    return dict(return_data)

A couple of notes:

  • If your document has additional field types, you need to enhance the helper function above.
  • The helper method above was inspired by Thomas' answer to a question. Additional functionality includes: recursively print out EmbeddedDocuments and include the id of the document.
Granny answered 24/12, 2012 at 20:45 Comment(1)
my_document.to_json() converts a MongoEngine document to JSON. It doesn't work to jsonify() that JSON though. I used json.loads() to convert it to a dict and then return jsonify() it, though there is probably a better way.Retraction
V
12

You can use mongoengine built-in method : to_json(). Example above that , you can use like this:

def show_results_async(text):
   query  =  { '$or':[{'title':{'$regex':text}},{'author':{'$regex':text}} ]}
   posts = Posts.objects(__raw__=(query))
   return jsonify(result = posts.to_json())
Vancouver answered 25/10, 2013 at 13:48 Comment(1)
Doesn't that backslash-escape quotes, since it's double json-ified? I needed to do something like jsonify(result=[json.loads(post.to_json()) for post in Posts.objects]).Retraction
G
5

tl,dr: There is no built-in function that'll convert a MongoEngine document to JSON. So you'll need to write your own.

In views.py:

def show_results_async(text):
   query  =  { '$or':[{'title':{'$regex':text}},{'author':{'$regex':text}} ]}
   posts = Posts.objects(__raw__=(query))
   return jsonify(result=posts.to_dict())

In post.py, add:

def to_dict(self):
   return helper.mongo_to_dict(self)

In helper.py:

def mongo_to_dict(obj):
    return_data = []

    if isinstance(obj, Document):
        return_data.append(("id",str(obj.id)))

    for field_name in obj._fields:

        if field_name in ("id",):
            continue

        data = obj._data[field_name]

        if isinstance(obj._fields[field_name], DateTimeField):
            return_data.append((field_name, str(data.isoformat())))
        elif isinstance(obj._fields[field_name], StringField):
            return_data.append((field_name, str(data)))
        elif isinstance(obj._fields[field_name], FloatField):
            return_data.append((field_name, float(data)))
        elif isinstance(obj._fields[field_name], IntField):
            return_data.append((field_name, int(data)))
        elif isinstance(obj._fields[field_name], ListField):
            return_data.append((field_name, data))
        elif isinstance(obj._fields[field_name], EmbeddedDocumentField):
            return_data.append((field_name, mongo_to_dict(data)))

    return dict(return_data)

A couple of notes:

  • If your document has additional field types, you need to enhance the helper function above.
  • The helper method above was inspired by Thomas' answer to a question. Additional functionality includes: recursively print out EmbeddedDocuments and include the id of the document.
Granny answered 24/12, 2012 at 20:45 Comment(1)
my_document.to_json() converts a MongoEngine document to JSON. It doesn't work to jsonify() that JSON though. I used json.loads() to convert it to a dict and then return jsonify() it, though there is probably a better way.Retraction
R
1

This works, though I don't know if it's the most efficient way:

import json

@app.route('/api/my-objects/')
def get_objects():
    all_objects = [json.loads(o.to_json()) for o in MyObject.objects]

    return jsonify({"my_objects": all_objects})
Retraction answered 11/12, 2015 at 20:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.