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

Literal values are not being correctly serialised for OpenAPI v3 #23

Closed
metamoof opened this issue Aug 18, 2023 · 4 comments
Closed

Literal values are not being correctly serialised for OpenAPI v3 #23

metamoof opened this issue Aug 18, 2023 · 4 comments

Comments

@metamoof
Copy link

I regularly deal with an API where a value is either something that fits some minimal requirements or is an empty string. I've made a small example here:

import sys
from typing import Literal

import pydantic
from openapi_pydantic.v3.v3_0_3 import OpenAPI
from openapi_pydantic.v3.v3_0_3.util import construct_open_api_with_schema_class
from pydantic import BaseModel, Field, constr

assert pydantic.__version__ == "2.0.2"
assert sys.version_info >= (3, 10)  # I use py 3.10


class Currency(BaseModel):
    currency: constr(min_length=3, max_length=3) | Literal[""] = Field(
        description="pong", example="pong"
    )


api = {
    "openapi": "3.0.3",
    "info": {
        "title": "A test API",
        "version": "1.0.0",
    },
    "paths": {
        "/ping": {
            "get": {
                "responses": {
                    "200": {
                        "description": "pong",
                        "content": {
                            "application/json": {
                                "schema": {"$ref": "#/components/schemas/Currency"}
                            }
                        },
                    }
                },
            }
        }
    },
}

open_api = OpenAPI.model_validate(api)
open_api = construct_open_api_with_schema_class(
    open_api, schema_classes=[Currency], by_alias=False
)

with open("test_output.json", "w") as f:
    f.write(open_api.model_dump_json(by_alias=True, exclude_none=True, indent=2))

The output from this is:

{
  "openapi": "3.0.3",
  "info": {
    "title": "A test API",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "paths": {
    "/ping": {
      "get": {
        "responses": {
          "200": {
            "description": "pong",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Currency"
                }
              }
            }
          }
        },
        "deprecated": false
      }
    }
  },
  "components": {
    "schemas": {
      "Currency": {
        "title": "Currency",
        "required": [
          "currency"
        ],
        "type": "object",
        "properties": {
          "currency": {
            "title": "Currency",
            "anyOf": [
              {
                "maxLength": 3,
                "minLength": 3,
                "type": "string"
              },
              {
                "const": ""
              }
            ],
            "description": "pong",
            "example": "pong"
          }
        }
      }
    }
  }
}

My syntax checker tells me const is not allowed in a property.

Presumably this is permissible under JSON Schemas, but the OpenAPI library should be replacing this with a second string block, filtering this out or otherwise flagging it.

@metamoof
Copy link
Author

I've created an appropriate GenerateJsonSchema object to try and pass to OpenAPI, but I can't see how to do that either....

@mike-oakley
Copy link
Owner

Looks like @hathawsh may be resolving this already? 77a58ca

@mike-oakley
Copy link
Owner

Hey @metamoof - version 0.4.0 has just been released which includes the fix I mentioned above - would you mind trying that and let me know if you still have issues? Closing this for now 👍🏼

@hosaka
Copy link

hosaka commented Jul 11, 2024

Not sure if intended, an enum with a single type will still get the "const" keyword in v3.0 (https://github.com/mike-oakley/openapi-pydantic/blob/main/openapi_pydantic/v3/v3_0_3/util.py#L108)

class InteractableType(str, Enum):
    """
    Interactable type.
    """

    IMAGE_DISPLAY = "IMAGE_DISPLAY"

will produce:

      "InteractableType": {
        "title": "InteractableType",
        "enum": [
          "IMAGE_DISPLAY"
        ],
        "type": "string",
        "description": "Interactable type.",
        "const": "IMAGE_DISPLAY"
      },

which openapi-generator-cli (for example) will complain about when generating code. If "const" is not a part of v3 spec, it should not be generated.

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