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

Invalid schema with types with primes (') #57

Open
brprice opened this issue Aug 10, 2022 · 0 comments
Open

Invalid schema with types with primes (') #57

brprice opened this issue Aug 10, 2022 · 0 comments

Comments

@brprice
Copy link

brprice commented Aug 10, 2022

When generically deriving a schema for a type whose name contains a ' we (might) generate a malformed spec.
(Such a type may come from being defined to have such a name, or mentioning a promoted constructor (with DataKinds).)
If the openapi3 generates a named schema object, it will be named the same as the type (applied to parameters, with spaces replaced by underscores).
Unfortunately, the spec https://swagger.io/specification/#components-object says this is invalid:

All the fixed fields declared above are objects that MUST use keys that match the regular expression: ^[a-zA-Z0-9\.\-_]+$

Both the online swagger editor and openapi-generator-cli validate reject the schema as invalid.

For example, consider the program

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeApplications #-}

module Main where

import qualified Data.ByteString.Lazy.Char8 as B
import Data.OpenApi
import Data.OpenApi.Declare
import Data.OpenApi.Internal.Utils
import Data.Proxy
import GHC.Generics

data A = A {x :: T'}
 deriving Generic

data T' = T'
  deriving Generic

instance ToSchema A
instance ToSchema T'

main :: IO ()
main = B.putStrLn $ encodePretty $  execDeclare (declareSchemaRef $ Proxy @A) mempty

This prints

{
    "A": {
        "properties": {
            "x": {
                "$ref": "#/components/schemas/T'"
            }
        },
        "required": [
            "x"
        ],
        "type": "object"
    },
    "T'": {
        "enum": [
            "T'"
        ],
        "type": "string"
    }
}

Notice that the map keys include the character '.

The solutions I can see are:

  • Just document this behaviour.
    It is unusual to manually name an API-visible type with a ', so it is not worth fixing -- a user can always change their data declaration.
    However, if a poorly-named type comes from an external library or a user is using DataKinds, they cannot simply rename.
    Thus we should also document a workaround (one can generically derive, and use rename)
  • Document this behaviour and also use a custom type error to statically forbid such instances.
    I don't know how possible this is for the "polymorphic type with a promoted argument" case.
  • Do some encoding of every named declaration.
    It would be nice if names without ' are not mangled, and we should ensure that the encoding is injective (to avoid name clashes). On this second point, see also Generically derived schema reference names can clash #56.
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

1 participant