-
-
Notifications
You must be signed in to change notification settings - Fork 791
Parsing of Array Query Parameters for REST Applications and OpenAPI Specification #3491
-
I'm curious how the community handles documenting and consuming array query parameters.
The documentation is very clear on approach for leveraging, for example, $select
within an application:
app.service('messages').find({ query: { $select: ['text', 'userId'] } })
I find the translation to REST query parameters confusing. There is an extra set of square bracket required: GET /messages?$select[]=text&$select[]=userId
.
The syntax, according to OpenAPI, seems to hint at an object query parameter in the deepObject
style, while the docs seem to align with a style: form
, explode: true
format.
The helpful feathers-swagger package generates a swagger UI that similarly doesn't understand how to parse and handle array query syntax. The UI generates that same query as GET /messages?$select=text&$select=userId
. This is valid, and returns results, but when requesting a single $select
value, the query validators throw, saying they require an array.
tldr; How do you document query parameters that take arrays in a way that is OpenAPI 3.X compliant and aligns with Feather's documentation?
This framework has been a ton of fun to use and learn. Learning how you all navigate this finer detail could really help my projects easily integrate into the the vast tooling surrounding OpenAPI specifications.
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 1 comment 5 replies
-
To make the problem slightly more complex, in OpenAPI 3.X nested query parameters are not supported. I'm wondering if the best approach is to flatten the query syntax into many options. Something like:
{ "//": "rest of spec", "parameters": [ { "in": "query", "name": "$sort[id]", "schema": { "type": "integer", "minumum": -1, "maximum": 1 } }, { "description": "Number of results to skip", "in": "query", "name": "$sort[text]", "schema": { "type": "integer", "minumum": -1, "maximum": 1 } }, { "description": "Number of results to skip", "in": "query", "name": "$sort[created]", "schema": { "type": "integer", "minumum": -1, "maximum": 1 } } ]
Beta Was this translation helpful? Give feedback.
All reactions
-
We found it's always better to be explicit so that would make sense. As for array handling, this should be the same behaviour (and configurability using the qs package) as in most other NodeJS framework I am aware of. For the case for a single select, I usually ended up normalizing any primitive value for $select
into an array before validation.
Beta Was this translation helpful? Give feedback.
All reactions
-
@daffl thanks for the engagement.
I think the conclusion, then is that feathers and feather-swagger won't seamlessly integrate with tools that are strictly OpenAPI 3.0 complaint. Additional middleware, hooks, post-processing, etc would be required to marry the usage of qs internally to the OpenAPI ecosystem.
If anyone has built something to this effect, or aware of an exiting tool to bridge the gap between the two, I'd appreciate you sharing.
Beta Was this translation helpful? Give feedback.
All reactions
-
It's a bit surprising that the qs package doesn't seem to be OpenAPI spec complaint. Still to get things like GET /messages?$select=text&$select=userId
and GET /messages?$select=text
should be fairly straightforward with something like this:
export const somethingQueryResolver = resolve<SomethingQuery, HookContext>({ $select: async (value, user, context) => { if (value !== undefined) { return Array.isArray(value) ? value: [ value ] } } })
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
-
💯 agreed.
For reference OAI/OpenAPI-Specification#3052 (comment) I came across that confirms OpenAPI's more limited query parameter scope.
Thanks for that snippet. Definitely a good reference. I'd written something similar as a one-off, but realized I want something more broad to help assist with $in and $nin for all queryable fields.
Beta Was this translation helpful? Give feedback.
All reactions
-
To be fair, we all experience similar necessary type guards in vanilla express where all query parameters must be optional, a primitive, or an array of primitives.
Beta Was this translation helpful? Give feedback.