According to the OpenAPI specification for the collectionFormat, there is an additional type multi to allow multiple parameter instances instead of multiple values for a single instance.
Connexion to support the collectionFormat of type multi.
Currently, Connexion does only support the types of csv, tsv and pipes.
How the bug could be reproduced?
Have you an example of a specification?
@lisitsky This is not a bug report, but a feature request.
I was able to create a very basic setup and test it. It appears to actually work. Not sure if it'll process validation rules on each query parameter passed though.
Swagger multi spec
swagger: '2.0'
info:
version: 0.0.0
title: Simple API
paths:
/:
get:
operationId: app.test
parameters:
- name: test
in: query
type: array
collectionFormat: multi
items:
type: string
responses:
200:
description: OK
Connexion code
import connexion
from flask import request, jsonify
app = connexion.App(__name__)
def test():
return jsonify(request.args.getlist('test'))
app.add_api('swagger.yaml')
app.run()
Results in Postman:
[
"1",
"2",
"3"
]
I would also need this feature. I could work on it.
@ibigpapa Do you mind share your code approach to continue ?
Flask Requests context uses the request.args.getlist('keyname') so we'd just need to ensure the elements of the list are validated and I think we'd be good at that point.
It's possible to use directly request.args.getlist('keyname') inside the operation called from the specification, it could work as a workaround but if you use:
/api/?dow=1&dow=2&dow=3
python
def test(dow):
return dow # dow is [1]
I was trying to get a test, adding here a proper test, but app_client.get(url, headers=headers) is not reading these kind of parameters correctly.
@chimeno How is this going? I also need this feature.
As I've said before, you could workaround this by using:
````python
from flask import request
def function_operation():
keyname = request.args.getlist('keyname')
````
As I've said before, I would like to work on this implementation, but I cannot give any time estimation due to being in my free time, so if @lhannest or others are interested in working on it, please do it.
@chimeno @ibigpapa I implemented a solution, though it's entirely within parameter.py. I'm not sure if other files need to be modified as well. But, from a bit of testing it appears to be working.
Take a look here where query parameters are being added. The request.query is a MultiDict object, and will contain multiple values for the same key in the case of the query using a muti-encoded list. But in such a case, only the first key-value pair are taken for a given key, and the rest are discarded. I changed things a bit so that if there are multiple instances of the same key it takes all mapped values as a list. And this is passed down to get_val_from_param, which I modified to handle cases where the value is a list.
Please review my work if you can, I am not familiar with this project so I'm not in any position to know whether my changes may have broken something: https://github.com/lhannest/connexion/commit/4c278c020f1826ec16a1c4f7ccb47c50402c24f9?diff=split
My specification file is large so I wont post it here, but c is an array and keywords is a string.
The URL parameters /api?c=hi&b=7&c=3&keywords=hi&keywords=no and the following code:
def get(c, keywords=None):
d = {'c' : c, 'keywords' : keywords }
return jsonify(d)
Results in:
{
"c": [
"hi",
"3"
],
"keywords": "hi"
}
Also the parameters /api?c=hi|joe&b=7&c=3&keywords=hi&keywords=no produces:
{
"c": [
"hi|joe",
"3"
],
"keywords": "hi"
}
Which I think is fair to expect, even though my settings for arrays are to be pipe delimited. I don't think users will wish to use a special character to delimit their arrays and also use multiple entries.
On the other hand, api/statements?c=hi|joe&b=7&keywords=hi&keywords=no produces:
{
"c": [
"hi",
"joe"
],
"keywords": "hi"
}
@lhannest would you be willing to do a PR? Thanks! :smile:
@hjacobs I put in two pull requests. The first one was failing automated tests, so I made the implementation even simpler and encapsulated it within a single method. I can't get tox to run tests locally, so I'm hoping this second time it will work.
With the same setup as before, api/statements?c=1&keywords=hello&c=2&keywords=no&c=5|6|7|8 produces:
{
"c": [
"1",
"2",
"5",
"6",
"7",
"8"
],
"keywords": "hello"
}
I haven't look at the code yet, but, wouldn't be the desired output like this?:
{
"c": [
"1",
"2",
"5",
"6",
"7",
"8"
],
"keywords": ["hello", "no]
}
Also I'm not sure if combine 'c' with pipes and c with 'multi' it's a good idea.
@chimeno keywords is a string, not an array. And the user shouldn't ever use multiple collection formats like that, anyway. I was just doing it for the sake of testing. I think it would be more important to keep the code simple, than to handle illegal inputs in the most intuitive way possible. But how else would you suggest handling that?
Most helpful comment
I would also need this feature. I could work on it.
@ibigpapa Do you mind share your code approach to continue ?