Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support deep objects for query parameters with deepObject style #1385

Open
bajtos opened this issue Sep 13, 2018 · 5 comments
Open

Support deep objects for query parameters with deepObject style #1385

bajtos opened this issue Sep 13, 2018 · 5 comments

Comments

@bajtos
Copy link
Contributor

bajtos commented Sep 13, 2018

Content & configuration

Swagger/OpenAPI definition:

parameters:
 filterParam:
   in: query
   name: filter
   schema:
     type: object
   style: deepObject
   explode: true
   description: Options for filtering the results
   required: false

Swagger-Client usage:

SwaggerClient({
  // no special configuration is needed
})

Is your feature request related to a problem?

Many applications expect deeply nested objects in input parameters, see the discussion in swagger-ui starting from this comment: swagger-api/swagger-ui#4064 (comment) In LoopBack, we are running into this problem too, see loopbackio/loopback-next#1679.

Consider the filter parameter described above (in:query style:deepObject explode:true).

Let's say the user provides the following value, for example by entering a JSON into the text area rendered by swagger-ui:

{
  "name": "ivan",
  "birth-date": {
    "gte": "1970-01-01"
  }
}

At the moment, swagger-js (and swagger-ui) silently ignores the value, produces an empty query and does not even let the user know that something went wrong.

Describe the solution you'd like

The following query string should be created by swagger-js client for the input value shown above.

filter[name]=ivan&filter[birth-date][qte]=1970-01-01

Describe alternatives you've considered

There are no alternatives as far as I can tell.

In the past, when Swagger 2.x did not support deepObject style, we were describing our filter argument as string and allowing clients to send the deep object in a JSON string. This was our custom extension that was of course not supported by swagger-js and swagger-ui, creating a suboptimal user experience.

Additional context

We are using swagger-ui-dist@3.17.0, which is the latest version published to npm. Unfortunately I am not able to tell which version of swagger-js is used by this version of swagger-ui-dist :(

The proposed serialization style is supported by https://www.npmjs.com/package/qs, which is used by http://expressjs.com as the default query parser, which means that a vast number of Node.js API servers are already expecting this serialization style.

I found the following two older comments that may be relevant:

#1140

Limitations:
deepObject does not handle nested objects. The specification and swagger.io documentation does not provide an example for serializing deep objects. Flat objects will be serialized into the deepObject style just fine.

#1140 (comment)

As for deepObject and nested objects - that was explicitly left out of the spec, and it's ok to just Not Support It™.

@shockey @webron What's your opinion on this? If we contributed a patch to swagger-js that will serialize deeply-nested properties using the style described above, would you accept such change, despite the fact that OpenAPI specification does not explicitly describe how to serialize deeply-nested properties?

@webron
Copy link
Contributor

webron commented Sep 22, 2018

@bajtos when we defined deepObject in the spec, we explicitly chose to not mention what happens when the object has several levels in it, but in our conversations we went with 'not supported'. If you're looking for supporting that use case, it needs to be addressed by the spec first.

@bajtos
Copy link
Contributor Author

bajtos commented Sep 25, 2018

@webron thank you for the response.

when we defined deepObject in the spec, we explicitly chose to not mention what happens when the object has several levels in it, but in our conversations we went with 'not supported'.

Fair enough. Can swagger-js reject deeply nested objects with a descriptive error then? Right now, swagger-ui is silently ignoring parameter values set to a deep object. I'd like it to display an error explaining the problem to the user.

Would you accept a patch adding such validation logic?

If you're looking for supporting that use case, it needs to be addressed by the spec first.

Makes sense. I have very little experience with the standardization process. What is your opinion - how likely will such proposal get accepted? How long would the process take? Is it a matter of weeks, months or years?

@webron
Copy link
Contributor

webron commented Sep 27, 2018

Providing a descriptive error makes sense to me, and we'd appreciate a patch for that logic.

To start a process with affecting the spec, you can file a ticket at https://github.com/OAI/OpenAPI-Specification/ with the details. Releases of the spec are not frequent, so it can take some time. Assuming it's a non-breaking change, it can get into a minor version (but cannot get into a patch version) - that would be a few months.

@bajtos
Copy link
Contributor Author

bajtos commented Oct 11, 2018

Thank you @webron. I opened a new ticket to enhance the spec, see OAI/OpenAPI-Specification#1706.

I'll try to find some time to fix swagger-js in the next few weeks.

deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 3, 2020
BREAKING CHANGE: This fix has modified the Open-API definition of the decorator
'param.query.object', to support url-encoded format for json query parameters.

Previously, such parameters were described with `exploded: true` and
`style: deepObject` which turned out to be problematic, as explained and
discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for json query params if the payload was
simple as below, but not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix modifies the definition
of JSON query params from `exploded` and `deep-object` style to the `url-encoded`
style described in Open-API spec.

The 'style' and 'explode' fields are removed. The 'schema' field is moved under
'content[application/json]' (`url-encoded` style) as below,

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

for example, to filter api results with the following condition,

```json
  {
    "include": [
      {

        "relation": "todo"
      }
    ]
  }
```

the following url-encoded query parameter is used.
```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

To preserve compatibility with existing REST API clients, this change is backward
compatible with all previously supported formats for json query parameters.
Exploded queries like `?filter[limit]=1` will continue to work, despite the fact
that they are described differently in the OpenAPI spec. As a result, existing
REST API clients will keep working after an upgrade.

LoopBack framework supported receiving `url-encoded` payload for `exploded`, `deep
object style` query params on the server side even before this fix, even though
the Open-API spec has very clear demarcations for both the styles.

In effect, this fix only clarifies the schema contract as per Open-API spec.

The signature of the 'param.query.object' decorator has not changed. There is no
code changes required in the LoopBack APIs after upgrading to this fix. No method
signatures or data structures are impacted.

The impact is only on the open api specifications generated from LoopBack APIs.
All consumers of LoopBack APIs may need to regenerate the api specifications, if
their API clients or client tools (like swagger-ui or LoopBack's api explorer)
necessiate adhering to Open-API's url-encoded query parameter definition to use
url-encoding.

Otherwise there wouldnt be any significant impact on API consumers.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 3, 2020
BREAKING CHANGE: This fix has modified the schema described by the decorator
'param.query.object', to support Open-API specification's url-encoded format for json
query parameters.

Previously, such parameters were described with `exploded: true`, `style: deepObject`
which turned out to be problematic, as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for json query params if the payload was simple as below,
but not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix modifies the definition of
JSON query params from `exploded` and `deep-object` style to the `url-encoded` style
described in Open-API spec.

The 'style' and 'explode' fields are removed. The 'schema' field is moved under
'content[application/json]' (`url-encoded` style) as below,

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

for example, to filter api results with the following condition,

```json
  {
    "include": [
      {

        "relation": "todo"
      }
    ]
  }
```

the following url-encoded query parameter is used.
```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

To preserve compatibility with existing REST API clients, this change is backward
compatible with all previously supported formats for json query parameters.
Exploded queries like `?filter[limit]=1` will continue to work, despite the fact that
they are described differently in the OpenAPI spec. As a result, existing REST API
clients will keep working after an upgrade.

LoopBack supported receiving `url-encoded` payload for `exploded`, `deep object` style
query params on the server side even before this fix, even though the Open-API spec
has very clear demarcations for both these styles.

In effect, this fix only clarifies the schema contract as per Open-API spec.

The signature of the 'param.query.object' decorator has not changed. There is no code
changes required in the LoopBack APIs after upgrading to this fix. No method
signatures or data structures are impacted.

The impact is only on the open api specifications generated from LoopBack APIs. All
consumers of LoopBack APIs may need to regenerate the api specifications, if their
API clients or client tools (like swagger-ui or LoopBack's api explorer) necessiate
adhering to Open-API's url-encoded query parameter definition to use url-encoding.

Otherwise there wouldnt be any significant impact on API consumers.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 3, 2020
BREAKING CHANGE: This fix has modified the schema described by the decorator
'param.query.object', to support Open-API specification's url-encoded format for json
query parameters.

Previously, such parameters were described with `exploded: true`, `style: deepObject`
which turned out to be problematic, as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for json query params if the payload was simple as below,
but not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix modifies the definition of
JSON query params from `exploded` and `deep-object` style to the `url-encoded` style
described in Open-API spec.

The 'style' and 'explode' fields are removed. The 'schema' field is moved under
'content[application/json]' (`url-encoded` style) as below,

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

for example, to filter api results with the following condition,

```json
  {
    "include": [
      {

        "relation": "todo"
      }
    ]
  }
```

the following url-encoded query parameter is used.
```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

To preserve compatibility with existing REST API clients, this change is backward
compatible with all previously supported formats for json query parameters.
Exploded queries like `?filter[limit]=1` will continue to work, despite the fact that
they are described differently in the OpenAPI spec. As a result, existing REST API
clients will keep working after an upgrade.

LoopBack supported receiving `url-encoded` payload for `exploded`, `deep object` style
query params on the server side even before this fix, even though the Open-API spec
has very clear demarcations for both these styles.

In effect, this fix only clarifies the schema contract as per Open-API spec.
The impact is only on the open api definitions generated from LoopBack APIs.

The signature of the 'param.query.object' decorator has not changed. There is no code
changes required in the LoopBack APIs after upgrading to this fix. No method
signatures or data structures are impacted.

All consumers of LoopBack APIs may need to regenerate api definitions, if their
API clients or client tools (like swagger-ui or LoopBack's api explorer) necessiate
using Open-API's `url-encoded` format to support url-encoding.

Otherwise there wouldn't be any significant impact on API consumers.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 3, 2020
BREAKING CHANGE: This fix has modified the schema definitions described by the
decorator 'param.query.object', to support Open-API's `url-encoded` definition for json
query parameters.

Previously, such parameters were described with `exploded: true`, `style: deepObject`
which turned out to be problematic, as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for json query params if the payload was simple as below but
not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix modifies the definition of json
query params from `exploded` and `deep-object` style to the `url-encoded` style
described in Open-API spec.

The 'style' and 'explode' fields are removed. The 'schema' field is moved under
'content[application/json]' (`url-encoded` style) as below,

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

for example, to filter api results with the following condition,

```json
  {
    "include": [
      {

        "relation": "todo"
      }
    ]
  }
```

the following url-encoded query parameter is used.
```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

To preserve compatibility with existing REST API clients, this change is backward
compatible with all previously supported formats for json query parameters.
Exploded queries like `?filter[limit]=1` will continue to work, despite the fact that
they are described differently in the OpenAPI spec. As a result, existing REST API
clients will keep working after an upgrade.

LoopBack supported receiving `url-encoded` payload for `exploded`, `deep object` style
query params on the server side even before this fix, even though the Open-API spec has
very clear demarcations for both these styles.

In effect, this fix only clarifies the schema contract as per Open-API spec. The impact
is only on the open api definitions generated from LoopBack APIs.

The signature of the 'param.query.object' decorator has not changed. There is no code
changes required in the LoopBack APIs after upgrading to this fix. No method
signatures or data structures are impacted.

All consumers of LoopBack APIs may need to regenerate api definitions, if their client
libraries (like swagger-ui or LoopBack's api explorer) necessiate using Open-API's
`url-encoded` format to support url-encoding.

Otherwise there wouldn't be any significant impact on API consumers.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 3, 2020
BREAKING CHANGE: This fix has modified the schema definitions described by the
decorator 'param.query.object', to support Open-API's `url-encoded` definition for json
query parameters.

Previously, such parameters were described with `exploded: true`, `style: deepObject`
which turned out to be problematic as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded style encoding worked if the payload was simple as below but not for complex
objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix modifies the definition of json
query params from `exploded` and `deep-object` style to the `url-encoded` style
described in Open-API spec.

Certain client libraries (like swagger-ui or LoopBack's api explorer) necessiate using
Open-API's `url-encoded` format to support "sending" url-encoded payload.

LoopBack supported "receiving" url-encoded payload for `exploded`, `deep object` style
query params on the server side even before this fix, even though the Open-API spec has
very clear demarcations for both these styles.

In effect, this fix only clarifies the schema contract as per Open-API spec. The impact
is only on the open api definitions generated from LoopBack APIs.

All consumers of LoopBack APIs may need to regenerate api definitions only if their
client libraries require them to do so for url-encoding.

Otherwise there wouldn't be any significant impact on API consumers.

This fix removes the 'style' and 'explode' fields from the definition of json query params.
The 'schema' field is moved under 'content[application/json]' (`url-encoded` style) as below,

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

for example, to filter api results with the following condition,

```json
  {
    "include": [
      {

        "relation": "todo"
      }
    ]
  }
```

the following url-encoded query parameter is used.
```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

To preserve compatibility with existing REST API clients, this change is backward
compatible with all previously supported formats for json query parameters.
Exploded queries like `?filter[limit]=1` will continue to work, despite the fact that
they are described differently in the OpenAPI spec. As a result, existing REST API
clients will keep working after an upgrade.

The signature of the 'param.query.object' decorator has not changed.

There is no code changes required in the LoopBack APIs after upgrading to this fix. No method
signatures or data structures are impacted.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 3, 2020
BREAKING CHANGE: This fix has modified the schema definitions described by the decorator
'param.query.object', to support Open-API's `url-encoded` definition for json query
parameters.

Previously, such parameters were described with `exploded: true`, `style: deepObject`
which turned out to be problematic as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for simple json objects as below but not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix modifies the definition of json
query params from `exploded` and `deep-object` style to the `url-encoded` style
described in Open-API spec.

for example, to filter api results with the following condition,

```json
  {
    "include": [
      {

        "relation": "todo"
      }
    ]
  }
```

the following url-encoded query parameter is used,

```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

Certain client libraries (like swagger-ui or LoopBack's api explorer) necessiate using
Open-API's `url-encoded` style definition for json query params to support "sending"
url-encoded payload.

LoopBack supported "receiving" url-encoded payload for `exploded`, `deep object` style
query params on the server side even before this fix, even though the Open-API spec has
very clear demarcations for both these styles.

In effect, this fix only clarifies the schema contract as per Open-API spec. The impact
is only on the open api definitions generated from LoopBack APIs.

All consumers of LoopBack APIs may need to regenerate api definitions only if their
client libraries require them to do so for url-encoding.

Otherwise there wouldn't be any significant impact on API consumers.

This fix removes the 'style' and 'explode' fields from the definition of json query params.
The 'schema' field is moved under 'content[application/json]' (`url-encoded` style) as below,

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

To preserve compatibility with existing REST API clients, this change is backward
compatible with all previously supported formats for json query parameters.
Exploded queries like `?filter[limit]=1` will continue to work, despite the fact that
they are described differently in the OpenAPI spec. As a result, existing REST API
clients will keep working after an upgrade.

The signature of the 'param.query.object' decorator has not changed.

There is no code changes required in the LoopBack APIs after upgrading to this fix. No method
signatures or data structures are impacted.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 4, 2020
BREAKING CHANGE: This fix has modified the api definitions described by the decorator
'param.query.object', to support Open-API's `url-encoded` style definition for json
query parameters.

Previously, such parameters were described with `exploded: true` and
`style: deepObject` which turned out to be problematic as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for simple json objects as below but not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix switches from the `exploded`,
`deep-object` style to the `url-encoded` style described in Open-API spec.

For instance, to filter api results from the GET '/todo-list' endpoint in the todo-list
example with a specific relation , say, { "include": [ { "relation": "todo" } ] }, the
following url-encoded query parameter can be used,

```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

This fix removes the 'style' and 'explode' fields (`exploded` `deep-object` style) and
moves the 'schema' field under 'content[application/json]' (`url-encoded` style) in
the Open-API definition as below,

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

Certain client libraries (like swagger-ui or LoopBack's api explorer) necessiate using
Open-API's `url-encoded` style definition for json query params to support "sending"
url-encoded payload.

LoopBack supported "receiving" url-encoded payload for `exploded`, `deep object` style
query params on the server side even before this fix, even though the Open-API spec has
described both these styles with clear demarcations.

In effect, this fix only clarifies the schema contract as per Open-API spec. The impact
is only on the open api definitions generated from LoopBack APIs.

All consumers of LoopBack APIs may need to regenerate api definitions only if their
client libraries require them to do so for url-encoding.

Otherwise there wouldn't be any significant impact on API consumers.

To preserve compatibility with existing REST API clients, this change is backward
compatible with all previously supported formats for json query parameters.
Exploded queries like `?filter[limit]=1` will continue to work, despite the fact that
they are described differently in the OpenAPI spec. As a result, existing REST API
clients will keep working after an upgrade.

The signature of the 'param.query.object' decorator has not changed.

There is no code changes required in the LoopBack APIs after upgrading to this fix.
No method signatures or data structures are impacted.

This fix has also modified the coercion behaviour for `in:query`, `deep-object` query
parameters by removing json parsing for them and the expectation is to pass in only
string values. But since the `exploded` `deep-object` style definition for query params
has been removed, this behaviour remains just an internal source code aspect as of now.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 4, 2020
BREAKING CHANGE: This fix has modified the api definitions described by the decorator
'param.query.object', to support Open-API's `url-encoded` definition for json query
parameters.

Previously, such parameters were described with `exploded: true` and
`style: deepObject` which turned out to be problematic as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for simple json objects as below but not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix switches definition of json
query params from the `exploded`, `deep-object` style to the `url-encoded` style
definition in Open-API spec.

LoopBack already supports receiving url-encoded payload for json query parameters.
For instance, to filter api results from the GET '/todo-list' endpoint in the
todo-list example with a specific relation, { "include": [ { "relation": "todo" } ] },
the following url-encoded query parameter can be used,

```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

The coercion behavior in LoopBack has always supported receiving url-encoded payload
for `exploded`, `deep object` style json query params before this fix. This fix has
modified that behavior by removing json parsing for `deep object` json query params.
Since the `exploded` `deep-object` definition has been removed from the
`param.query.object` decorator, this new behaviour remains just an internal source
code aspect as of now.

In effect, this fix only clarifies the schema contract as per Open-API spec.

The impact is only on the open api definitions generated from LoopBack APIs.
This fix removes the 'style' and 'explode' fields from the definition of json query
params and moves the 'schema' field under 'content[application/json]'. This is the
definition that should support url-encoding as per Open-API spec.

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

Certain client libraries (like swagger-ui or LoopBack's api explorer) necessiate
using Open-API's `url-encoded` style definition for json query params to support
"sending" url-encoded payload.

All consumers of LoopBack APIs may need to regenerate api definitions, if their
client libraries require them to do so for url-encoding.

Otherwise there wouldn't be any significant impact on API consumers.

To preserve compatibility with existing REST API clients, this change is backward
compatible with all previously supported formats for json query parameters.
Exploded queries like `?filter[limit]=1` will continue to work for json query
params, despite the fact that they are described differently in the OpenAPI spec.
As a result, existing REST API clients will keep working after an upgrade.

The signature of the 'param.query.object' decorator has not changed.

There is no code changes required in the LoopBack APIs after upgrading to this
fix. No method signatures or data structures are impacted.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 4, 2020
BREAKING CHANGE: This fix has modified the api definitions described by the decorator
'param.query.object', to support Open-API's `url-encoded` definition for json query
parameters.

Previously, such parameters were described with `exploded: true` and
`style: deepObject` which turned out to be problematic as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for simple json objects as below but not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix switches definition of json
query params from the `exploded`, `deep-object` style to the `url-encoded` style
definition in Open-API spec.

LoopBack already supports receiving url-encoded payload for json query parameters.

For instance, to filter api results from the GET '/todo-list' endpoint in the
todo-list example with a specific relation, { "include": [ { "relation": "todo" } ] },
the following url-encoded query parameter can be used,

```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

The above was possible because the coercion behavior in LoopBack performed json
parsing for `deep object` style json query params before this fix. This fix has
modified that behavior by removing json parsing. Since the `exploded` `deep-object`
definition has been removed from the `param.query.object` decorator, this new
behaviour remains just an internal source code aspect as of now.

In effect, this fix only modifies the open api definitions generated from LoopBack
APIs. This fix removes the 'style' and 'explode' fields from the definition of
json query params and moves the 'schema' field under 'content[application/json]'.
This is the definition that supports url-encoding as per Open-API spec.

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

Certain client libraries (like swagger-ui or LoopBack's api explorer) necessiate
using Open-API's `url-encoded` style definition for json query params to support
"sending" url-encoded payload.

All consumers of LoopBack APIs may need to regenerate api definitions, if their
client libraries require them to do so for url-encoding.

Otherwise there wouldn't be any significant impact on API consumers.

To preserve compatibility with existing REST API clients, this change is backward
compatible. All exploded queries like `?filter[limit]=1` will continue to work for
json query params, despite the fact that they are described differently in the
OpenAPI spec.

Existing api clients will continue to work after an upgrade.

The signature of the 'param.query.object' decorator has not changed.

There is no code changes required in the LoopBack APIs after upgrading to this
fix. No method signatures or data structures are impacted.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 4, 2020
BREAKING CHANGE: This fix has modified the api definitions described by the decorator
'param.query.object', to support Open-API's `url-encoded` definition for json query
parameters.

Previously, such parameters were described with `exploded: true` and
`style: deepObject`, i.e exploded encoding, which turned out to be problematic as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for simple json objects as below but not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix switches definition of json
query params from the `exploded`, `deep-object` style to the `url-encoded` style
definition in Open-API spec.

LoopBack already supports receiving url-encoded payload for json query parameters.

For instance, to filter api results from the GET '/todo-list' endpoint in the
todo-list example with a specific relation, { "include": [ { "relation": "todo" } ] },
the following url-encoded query parameter can be used,

```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

The above was possible because the coercion behavior in LoopBack performed json
parsing for `deep object` style json query params before this fix. This fix has
modified that behavior by removing json parsing. Since the `exploded` `deep-object`
definition has been removed from the `param.query.object` decorator, this new
behaviour remains just an internal source code aspect as of now.

In effect, this fix only modifies the open api definitions generated from LoopBack
APIs. The 'style' and 'explode' fields are removed and the 'schema' field is moved
under 'content[application/json]'. This is the definition that supports url-encoding
as per Open-API spec.

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

Certain client libraries (like swagger-ui or LoopBack's api explorer) necessiate
using Open-API's `url-encoded` style definition for json query params to support
"sending" url-encoded payload.

All consumers of LoopBack APIs may need to regenerate api definitions, if their
client libraries require them to do so for url-encoding.

Otherwise there wouldn't be any significant impact on API consumers.

To preserve compatibility with existing REST API clients, this change is backward
compatible. All exploded queries like `?filter[limit]=1` will continue to work for
json query params, despite the fact that they are described differently in the
OpenAPI spec.

Existing api clients will continue to work after an upgrade.

The signature of the 'param.query.object' decorator has not changed.

There is no code changes required in the LoopBack APIs after upgrading to this
fix. No method signatures or data structures are impacted.
deepakrkris added a commit to loopbackio/loopback-next that referenced this issue Feb 6, 2020
BREAKING CHANGE: This fix has modified the api definitions described by the decorator
'param.query.object', to support Open-API's `url-encoded` definition for json query
parameters.

Previously, such parameters were described with `exploded: true` and
`style: deepObject`, i.e exploded encoding, which turned out to be problematic as explained and discussed in,
swagger-api/swagger-js#1385 and
OAI/OpenAPI-Specification#1706

```json
  {
    "in": "query",
    "style": "deepObject"
    "explode": "true",
    "schema": {}
  }
```

Exploded encoding worked for simple json objects as below but not for complex objects.

```
   http://localhost:3000/todos?filter[limit]=2
```

To address these issues with exploded queries, this fix switches definition of json
query params from the `exploded`, `deep-object` style to the `url-encoded` style
definition in Open-API spec.

LoopBack already supports receiving url-encoded payload for json query parameters.

For instance, to filter api results from the GET '/todo-list' endpoint in the
todo-list example with a specific relation, { "include": [ { "relation": "todo" } ] },
the following url-encoded query parameter can be used,

```
   http://localhost:3000/todos?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22todoList%22%7D%5D%7D
```

The above was possible because the coercion behavior in LoopBack performed json
parsing for `deep object` style json query params before this fix. This fix has
modified that behavior by removing json parsing. Since the `exploded` `deep-object`
definition has been removed from the `param.query.object` decorator, this new
behaviour remains just an internal source code aspect as of now.

In effect, this fix only modifies the open api definitions generated from LoopBack
APIs. The 'style' and 'explode' fields are removed and the 'schema' field is moved
under 'content[application/json]'. This is the definition that supports url-encoding
as per Open-API spec.

```json
  {
    "in": "query"
    "content": {
      "application/json": {
        "schema": {}
      }
    }
  }
```

Certain client libraries (like swagger-ui or LoopBack's api explorer) necessiate
using Open-API's `url-encoded` style definition for json query params to support
"sending" url-encoded payload.

All consumers of LoopBack APIs may need to regenerate api definitions, if their
client libraries require them to do so for url-encoding.

Otherwise there wouldn't be any significant impact on API consumers.

To preserve compatibility with existing REST API clients, this change is backward
compatible. All exploded queries like `?filter[limit]=1` will continue to work for
json query params, despite the fact that they are described differently in the
OpenAPI spec.

Existing api clients will continue to work after an upgrade.

The signature of the 'param.query.object' decorator has not changed.

There is no code changes required in the LoopBack APIs after upgrading to this
fix. No method signatures or data structures are impacted.
@Adhalianna
Copy link

Adhalianna commented Jul 6, 2023

Since the discussion on the OAS side seems to have stopped on "use extensions", maybe Swagger could support one that implements this? Some suggestions have been proposed here in the comment under the discussion started by @bajtos .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants