Can't Return JSON object using MongoEngine Pym

2020-07-10 07:43发布

问题:

So I'm trying to return a JSON object for a project. I've spent a few hours trying to get Django just returning the JSON.

Heres the view that we've been working with:

def json(request, first_name):
    user = User.objects.all()
    #user = User.objects.all().values()
    result = simplejson.dumps(user, default=json_util.default)
    return HttpResponse(result)

Here's my model:

class User(Document):  
    gender = StringField( choices=['male', 'female', 'Unknown']) 
    age = IntField()
    email = EmailField()
    display_name = StringField(max_length=50)
    first_name = StringField(max_length=50)
    last_name = StringField(max_length=50)
    location = StringField(max_length=50)
    status = StringField(max_length=50)
    hideStatus = BooleanField()
    photos = ListField(EmbeddedDocumentField('Photo')) 
    profile =ListField(EmbeddedDocumentField('ProfileItem'))
    allProfile = ListField(EmbeddedDocumentField('ProfileItem')) #only return for your own profile

This is what it's returning:

[<User: User object>, <User: User object>] is not JSON serializable

Any thoughts on how I can just return the JSON?

回答1:

With MongoEngine 0.8 or greater, objects and querysets have a to_json() method.

>>> User.objects.to_json()


回答2:

simplejson.dumps() doesn't know how to "reach into" your custom objects; the default function, json_util.default must just be calling str() or repr() on your documents. (Is json_util custom code you've written? If so, showing its source here could prove my claim.)

Ultimately, your default function will need to be able to make sense of the MongoEngine documents. I can think of at least two ways that this might be implemented:

  1. Write a custom default function that works for all MongoEngine documents by introspecting their _fields attribute (though note that the leading underscore means that this is part of the private API/implementation detail of MongoEngine and may be subject to change in future versions)

  2. Have each of your documents implement a as_dict method which returns a dictionary representation of the object. This would work similarly to the to_mongo method provided on documents by MongoEngine, but shouldn't return the _types or _cls fields (again, these are implementation details of MongoEngine).

I'd suggest you go with option #2: the code will be cleaner and easier to read, better encapsulated, and won't require using any private APIs.



回答3:

As dcrosta suggested you can do something like this, hope that will help you.

Document definition

class MyDocument(Document):
    # Your document definition

    def to_dict(self):
        return mongo_to_dict_helper(self)

helper.py:

from mongoengine import StringField, ListField, IntField, FloatField

def mongo_to_dict_helper(obj):
    return_data = []
    for field_name in obj._fields:
        if field_name in ("id",):
            continue

        data = obj._data[field_name]

        if 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))
        else:
            # You can define your logic for returning elements
    return dict(return_data)