Search code examples
swaggerfastapiopenapiinsomnia

FastAPI's auto generated OpenAPI file not valid according to Insomnia


I am trying to import an openapi.json into Insomnia to generate a collection, but Insomnia says it is not valid.

Is there a difference in rulesets between FastAPI/Swagger and Insomnia? If not, what causes this difference in compatibility?

Here's a trimmed down example of an automatically generated OpenAPI specification:

{
    "openapi": "3.0.2",
    "info": {
        "title": "Test API",
        "description": "description",
        "contact": {
            "name": "example",
            "url": "https://example.com/contact-us/",
            "email": "[email protected]"
        },
        "license": {
            "name": "Copyright 2023 example"
        },
        "version": "0.0.1"
    },
    "paths": {
        "/test_build": {
            "get": {
                "tags": [
                    "Test endpoints"
                ],
                "summary": "Test",
                "description": "",
                "operationId": "test_build_get",
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {}
                            }
                        }
                    }
                }
            }
        },
        "/api/search_something": {
            "get": {
                "tags": [
                    "Main endpoints"
                ],
                "summary": "Search something",
                "description": "",
                "operationId": "search_something_get",
                "parameters": [
                    {
                        "required": false,
                        "schema": {
                            "title": "something",
                            "maximum": 50.0,
                            "exclusiveMinimum": 0.0,
                            "type": "integer",
                            "default": 50
                        },
                        "name": "something",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {}
                    }
                }
            }
        }
    }
}

This is rejected by Insomnia for many reasons, but here are some examples of errors and warnings:

  • oas3-api-servers OpenAPI "servers" must be present and non-empty array.
  • operation-tag-defined Operation tags must be defined in global tags.
  • oas3-schema "exclusiveMinimum" property type must be boolean.
  • oas3-valid-schema-example schema is invalid: data must have property minimum when property exclusiveMinimum is present

Is there a way to make FastAPI's openapi.json file conform with Insomnia's ruleset?


Solution

  • oas3-schema "exclusiveMinimum" property type must be boolean.

    exclusiveMinimum and exclusiveMaximum being generated as numbers instead of booleans is a known issue with Pydantic. Pydantic generates these keywords as numbers according to JSON Schema Draft 6+, but OpenAPI 3.0.x uses an earlier JSON Schema Draft 5 where the exclusive* keywords are booleans.

    This won't be an issue if/when FastAPI and Pydantic migrate to OpenAPI 3.1 because it uses the latest JSON Schema.

    But if you need to use OpenAPI 3.0.x, you have the following options.

    Option 1: use ge/le instead of gt/lt (if suitable)

    In case of integer parameters and schema fields, the easiest fix is to use the ge/le attributes ("greater/less than or equal") instead of gt/lt ("greater/less than"). For example, if the minimum value is 1 (inclusive), use ge=1 instead of gt=0:

    something: int = Query(ge=1)
    

    Pydantic translates ge to minimum and le to maximum without exclusive*.

    Option 2: post-process the OpenAPI file

    Another solution is to post-process your generated OpenAPI file (e.g. as suggested here) and replace

    "exclusiveMinimum": <value>
    

    with

    "minimum": <value>,
    "exclusiveMinimum": true
    

    Similarly, replace

    "exclusiveMaximum": <value>
    

    with

    "maximum": <value>,
    "exclusiveMaximum": true