RequestParser json list shown as type string in swagger json
If I create a request parser with an argument whose location is json and type list, in the api swagger json I see this argument as type string. I would have expected this to be shown as an array with items of type string. Am I right to expect this? Or is there some reason why it is shown as type string?
Steps to reproduce
- Create a python script
issue.pywith the following:
from flask import Flask
from flask_restx import Api, Resource, reqparse
app = Flask(__name__)
api = Api(app)
request_parser = reqparse.RequestParser(bundle_errors=True)
request_parser.add_argument('list', location='json', type=list)
@api.route('/test_list')
class TestList(Resource):
@api.expect(request_parser)
def get(self):
return {}
app.run()
- Run the script
python3 issue.py
- Get the swagger json
curl http://127.0.0.1:5000/swagger.json | python3 -mjson.tool
In the printed json you would observe the type of list as string
...
"schema": {
"type": "object",
"properties": {
"list": {
"type": "string"
}
}
}
...
After creating this issue I saw https://github.com/python-restx/flask-restx/issues/59 (did not read it all) which makes me think that any issues related to RequestParser will not be fixed. I have noted that I can get the behavior that I want by creating a model from a json schema and expecting the model. Is this a good approach to achieve this which hopefully will not be affected by future changes related to issue https://github.com/python-restx/flask-restx/issues/59? What worked for me is the following:
from flask import Flask, request
from flask_restx import Api, Resource
app = Flask(__name__)
api = Api(app)
request_schema = {
'type': 'object',
'properties': {
'list': {
'type': 'array',
'items': {'type': 'string'},
'minItems': 1,
},
},
'additionalProperties': False,
'required': ['list'],
}
request_model = api.schema_model('test_list_request', request_schema)
@api.route('/test_list')
class TestList(Resource):
@api.expect(request_model, validate=True)
def get(self):
print(request.json)
return request.json
app.run()
I have a similar issue with file uploads:
Swagger.json shows a string type for the parser argument image. Hence, no File Upload Button
uploadParser = reqparse.RequestParser()
uploadParser.add_argument('image', type=werkzeug.datastructures.FileStorage, required=True)
class UploadImage(Resource):
@api.expect(uploadParser)
def post(self):
args = uploadParser.parse_args()
uploaded_file = args['image'] # This is FileStorage instance
filename = secure_filename(uploaded_file.filename)
return {'url': filename}, 201
After creating this issue I saw #59 (did not read it all) which makes me think that any issues related to RequestParser will not be fixed. I have noted that I can get the behavior that I want by creating a model from a json schema and expecting the model. Is this a good approach to achieve this which hopefully will not be affected by future changes related to issue #59? What worked for me is the following:
from flask import Flask, request from flask_restx import Api, Resource app = Flask(__name__) api = Api(app) request_schema = { 'type': 'object', 'properties': { 'list': { 'type': 'array', 'items': {'type': 'string'}, 'minItems': 1, }, }, 'additionalProperties': False, 'required': ['list'], } request_model = api.schema_model('test_list_request', request_schema) @api.route('/test_list') class TestList(Resource): @api.expect(request_model, validate=True) def get(self): print(request.json) return request.json app.run()
I also faced this problem.
After reading the documentation, I have to add this lines of code to render type list parameter. But i still use the request parser to validate the request. It's just a temporary solution, because we have to write the parameters twice, both for documentation and for receiving the parameters.
add_photo_parser = reqparse.RequestParser()
add_photo_parser.add_argument('photo_url', type=list, location='json', help='Photo URL', required=True)
add_photo_fields = api.model('Add Photo', {
'photo_url': fields.List(fields.String)
})
@api.doc('projects_add_photo', description='Add photo to project', body=add_photo_fields)
@api.expect(add_photo_fields, validate=True)
@api.marshal_with(project_photos_serializer)
def post(self, project_id):
args = self.add_photo_parser.parse_args()
I have a similar issue with file uploads:
Swagger.json shows a string type for the parser argument image. Hence, no File Upload Button
uploadParser = reqparse.RequestParser() uploadParser.add_argument('image', type=werkzeug.datastructures.FileStorage, required=True) class UploadImage(Resource): @api.expect(uploadParser) def post(self): args = uploadParser.parse_args() uploaded_file = args['image'] # This is FileStorage instance filename = secure_filename(uploaded_file.filename) return {'url': filename}, 201
Add location='files'
uploadParser.add_argument('image', location='files', type=werkzeug.datastructures.FileStorage, required=True)
Still not fix yet?