closeio/flask-mongorest

Allow for custom Encoder class

jpnauta opened this issue · 1 comments

I have created a custom mongoengine document field EnumField.

class MyDocument(Document):
    my_enum = EnumField(MyEnum)

I also created a Resource and ResourceView for this class

class MyDocumentResource(Resource):
    document = MyDocument

@api.register(name='my_documents', url='/api/my-documents/')
class MyDocumentView(ResourceView):
    resource = MyDocumentResource
    methods = [methods.Create, methods.Update, methods.Fetch, methods.List]

However, when I call GET /api/my-documents/, I get the error:

unbound method default() must be called with JSONEncoder instance as first argument

This is caused because the JSONEncoder does not know how to encode an enum instance. I looked into the MongoEncoder class, and noticed that I could add some custom logic there.

class MyMongoEncoder(MongoEncoder):
    def default(self, value, **kwargs):
        if isinstance(value, Enum):
            return unicode(value.value)
        return super(BaseMongoEncoder, self).default(value, **kwargs)

However, I couldn't easily override the MongoEncoder class because it's hard coded here.

I ended up copy-pasting ResourceView.dispatch_request into my own MyResourceView.dispatch_request and creating my own render_json method, but this isn't a very clean method of doing making this work. Is there a better way to do this? If not, there should possibly be a way to specify your own render_json method and/or custom encoder class.

FYI It looks like this issue is already resolved, but this feature would also provide a workaround for this issue.

Feel free to submit a PR. Right now you'd have to override the views' dispatch_request and redecorate it with a custom mimerender decorator.