Search code examples
pythonpython-3.xflaskswaggerflask-restplus

How to properly render array parameter with swagger and flask restplus?


I am implementing a Flask Application with Flask RestPlus that must receive a list of ids (integers) on a HTTP GET endpoint, so the application client can get a list of results matching those identifiers, for instance, with...

GET /resource/1,2,3,4
GET /resource?id=1,2,3
GET /resource?id=1&id=2&id=3

... which is not supported by default by none of werkzeug bultin converters, but following the steps in this stackoverflow post the url parsing is working properly and I can receive the list of ids with this converter...

class ListOfIntegerConverter(BaseConverter):
    def __init__(self, url_map, randomify=False):
        self.regex = r'\d+(?:,\d+)*,?'

    def to_python(self, value):
        return [int(x) for x in value.split(',')]

    def to_url(self, value):
        return ','.join(str(x) for x in value)

... which is then properly registered as stated here ...

app.url_map.converters['list_of_int'] = ListOfIntegerConverter

... and used to parse the url parameters ...

@my_namespace.route('/<list_of_int:list_of_ids>/', methods=["GET"])
class MyResourceById(Resource):
    def get(self, list_of_ids):
        [print(id, type(id)) for id in list_of_ids]

... but the generated swagger documentation is rendering the field as a plain string instead of an array or list of integers, which should be rendered like this...

swagger list of integers

I know that swagger supports multi-value parameters, but I can't manage to make Flask RestPlus render this field accordingly. Is there anyone who knows how to do it that can help me out with some advice?

Thanks in advance! :)


Solution

  • I think you have to use arg parsers:

    id_parser = api.parser()
    id_parser.add_argument('id[]', type=int, action='append')
    
    @api.route('/ids', methods=["GET"])
    @api.doc(parser=id_parser)
    class MyResourceById(Resource):
    
        @staticmethod
        def get():
            ids = request.args.getlist('id[]')
            print(ids)
            return ids
    

    I'd do it as above, but you can probably get it working with your converter too.

    The documents say parser is being deprecated but not anytime soon, and I couldn't personally find an alternative.