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

OpenAPI 3.1.0 support: OpenAPI 3.1 type: […, "null"] incomplete support in parameters #9056

Open
commonism opened this issue Jul 24, 2023 · 6 comments

Comments

@commonism
Copy link

Q&A (please complete the following information)

  • OS: Ubuntu
  • Browser: Firefox
  • Version: 114.0.2
  • Method of installation: apt
  • Swagger-UI version: https://editor-next.swagger.io/
  • Swagger/OpenAPI version: 3.1

Content & configuration

Example Swagger/OpenAPI definition:
https://gist.github.com/commonism/7adcb666278f4070b8f7aabd456faa43

openapi: 3.1.0
info:
  title: ''
  version: 0.0.0
servers:
  - url: http://127.0.0.1/api

security:
  - {}

paths:
  /{path}:
    parameters:
      - $ref: "#/components/parameters/path"
      - $ref: '#/components/parameters/cookie'

    post:
      operationId: post
      requestBody:
        description: "!"
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Any'

      responses:
        '200':
          description: "!"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Any"

      callbacks:
        onData:
          '{$request.query.callbackUrl}/data':
            post:
              requestBody:
                description: "!"
                content:
                  application/json:
                    schema:
                      $ref: "#/components/schemas/Any"
              responses:
                '200':
                  description: "!"
                  content:
                    application/json:
                      schema:
                        $ref: "#/components/schemas/Any"



    get:
      operationId: get
      parameters:
      - $ref: "#/components/parameters/query"
      - $ref: "#/components/parameters/header"

      responses: &resp
        '200':
          description: "!"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Any'
          headers:
            head:
              $ref: "#/components/headers/header"



components:
  schemas:
    Any:
      type: [integer, string, object, array, boolean, "null"]
      items:
        $ref: "#/components/schemas/Any"
      properties:
        next:
          $ref: "#/components/schemas/Any"

  headers:
    header:
      schema:
          $ref: "#/components/schemas/Any"
      style: simple
      explode: false

  parameters:

    query:
      in: query
      name: query
      style: deepObject
      explode: true
      required: true
      schema:
        $ref: "#/components/schemas/Any"

    path:
      in: path
      name: path
      required: true
      schema:
        type: [string, "null"]

    header:
      in: header
      name: header
      required: true
      schema:
        type: [string, "null"]

    cookie:
      in: cookie
      name: cookie
      required: true
      schema:
        type: [string, "null"]

Describe the bug you're encountering

The rendering of the parameters does not reflect the use of OpenAPI 3.1 type as a list.
The use of "null" as list element to indicate "nullable" is not reflected as well.

To reproduce...

Steps to reproduce the behavior:
Paste the yaml to swagger editor.

Expected behavior

Screenshots

Bad types for Response & header
image

all Parameters
image

Callback Response
image

but works for a RequestBody
image

Additional context or thoughts

type: […, "null"] is the preferable way to define nullable in v3.1, using the alternative anyOf: […,{type: "null"}] instead results in a additional/unnecessary level of indirection in models generated from description documents.

@char0n char0n changed the title OpenAPI 3.1 type: […, "null"] incomplete support in parameters OpenAPI 3.1.0 support: OpenAPI 3.1 type: […, "null"] incomplete support in parameters Nov 13, 2023
@ChMThiel
Copy link

ChMThiel commented Dec 13, 2024

I'm confused:

  1. Here Clarification on nullable properties, OpenAPI 3.1 OAI/OpenAPI-Specification#3148 @handrews states that both ways (type: […, "null"] and anyOf: […,{type: "null"}]) are are supported in OAS 3.1
  2. But here describing nullable field by anyOf leads to bad swagger-ui smallrye/smallrye-open-api#2094 (comment) @MikeEdgar describes convincingly that combining $ref with type: […, "null"] is invalid
  3. @commonism says above "...type: […, "null"] is the preferable way to define nullable in v3.1, using the alternative anyOf: […,{type: "null"}] ..."

So openApi generated by smallrye with Quarkus3.17 is valid according to JSON-Schema (using the anyOf-way) but it's rendered badly in swagger-ui (real type is shown deeply nested, see smallrye/smallrye-open-api#2094 (comment)).

The question is: Is it possible to get a nicely rendered swagger-ui (with type-info not deeply nested but at the top like in the screenshot) with valid openApi.yaml according to [2]
grafik
(screenshot from smallrye/smallrye-open-api#2094)

@handrews
Copy link

@ChMThiel there isn't any conflict here. What @MikeEdgar seems to be pointing out is that if you $ref a schema with type: "string", you can't just stick a type: "null" next to the $ref have it be the same as an anyOf. This is true: adjacent keyword results are ANDed (like allOf) and not ORed (like anyOf).

So you have to use anyOf to "add" type: "null" to the set of available types. This works because no other keywords apply to type: "null", so it doesn't really matter what else is in the schema containing type: "string" on the other end of the $ref.

What's different about the example that I answered is that the two options were 1.) have both types in the same type keyword (type: ["string", "null"]) or 2.) put each type in a separate anyOf branch. At no point in that issue I answered does it say that you can just put type: "null" next to a $ref and have that work.

@ChMThiel
Copy link

ChMThiel commented Dec 16, 2024

Ok, than anyOfis the way to describe nullability.
But if so, the null/type-info is rendered in swagger-ui in a much less comprehensive way, as it was using OpenApi 3.0.3 (that's why i got a ticket in my company, see smallrye/smallrye-open-api#2094):

  • 3.0.3 grafik
  • 3.1.0 grafik

Afaik the anyOf was orginaly intend to be used for multiple types (like inheritance: e.g. anyOf plant: tree, bush, flower, etc.) In such a case the 3.1.0-way of rendereing is just fine.

The special case that a value has just one type (in my example a LocalTime) but can be null is a very common thing (at least in my APIs). Rendering that special case in swagger-ui as 'ordinary' anyOf's is imho not optimal (compared with the 'old' 3.0.3 way: in 3.0.3 you see the 'real' local-time type on first level; in 3.1.0 you have expand/klick all the way down, at first glance on first level it looks like a string-value).

Isn't there a posibility that swagger-ui renders the type/null-information at least for one type/null anyOf's in a better way and not so deeply nested?

@commonism
Copy link
Author

When this was written - swagger-ui does not support type-lists as type: […, null].
`anyOf: [{type: null}] was a workaround to have swagger-ui render nullable in 3.1.

This has changed over time:

Some improved:
image

Others … not:
image

@handrews
Copy link

Afaik the anyOf was orginaly intend to be used for multiple types (like inheritance: e.g. anyOf plant: tree, bush, flower, etc.) In such a case the 3.1.0-way of rendereing is just fine.

anyOf is just a non-exclusive OR. It has no inherent semantics beyond that.

When using null, as long as the other option(s) don't accept null then you can use oneOf safely as an alternative. But do be careful with this- a schema like {"minimum": 1} will accept null (but {"type": "integer", "minimum": 1} will not).

@ChMThiel
Copy link

ChMThiel commented Dec 17, 2024

Afaik the anyOf was orginaly intend to be used for multiple types (like inheritance: e.g. anyOf plant: tree, bush, flower, etc.) In such a case the 3.1.0-way of rendereing is just fine.

anyOf is just a non-exclusive OR. It has no inherent semantics beyond that.

When using null, as long as the other option(s) don't accept null then you can use oneOf safely as an alternative. But do be careful with this- a schema like {"minimum": 1} will accept null (but {"type": "integer", "minimum": 1} will not).

I'm using quarkus that generates the openApi.yml - with anyOf for the null-info. So (even if i wanted to) i have very limited options to change this. And as the discussion here shows, using anyOf seem to be the right way to do that (so i closed smallrye/smallrye-open-api#2094).

All i`m pointing out is that the type-info in the special case that a value has just one type but can be null, is rendered not as comprehensive as it was in OpenAPi 3.0.3.

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

No branches or pull requests

3 participants