-
Notifications
You must be signed in to change notification settings - Fork 62
Description
Description
It seems we generate invalid schemas for all tuples and Maps with "complex" keys (those that aeson's toJSONKey is ToJSONKeyValue and thus the map is encoded as an array of key-value pairs, rather than as a json object).
This is because Map k v is encoded the same as [(k,v)] for these keys, and (k,v) generates a schema similar to
{
"minItems": 2,
"items": [
{
"type": "string"
},
{
"type": "boolean"
}
],
"maxItems": 2,
"type": "array"
}
According to the OpenAPI3 spec, the items field must not be an array.
items - Value MUST be an object and not an array
More details
Note that even homogenous tuples (e.g. (String,String)) have the same problem, since there is no special handling.
In fact, due to this restriction I don't see how to give a schema for any non-record product type, unless all its fields have the same type.
A full example, generating an invalid spec is
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
import Control.Lens
import Data.Aeson.Encode.Pretty (encodePretty)
import Data.ByteString.Lazy.Char8 as BSL
import Data.Map (Map)
import Data.Proxy
import Data.OpenApi
main :: IO ()
main = BSL.putStrLn $ encodePretty $ (mempty :: OpenApi) &
components . schemas .~ [ ("Buggy", toSchema (Proxy :: Proxy (Map [Int] Bool)))]
(See also this gist for the generated schema, and a few other examples)
The output of this is rejected as by https://validator.swagger.io/validator
and https://editor.swagger.io/ and https://openapi-generator.tech/ (both of which give more useful error messages)
The code that constructs these specs
- https://hackage.haskell.org/package/openapi3-3.1.0/docs/src/Data.OpenApi.Internal.Schema.html#line-695 says
ToSchema (Map k v) = ToSchema [(k,v)]for "complex" keys - https://hackage.haskell.org/package/openapi3-3.1.0/docs/src/Data.OpenApi.Internal.Schema.html#line-583 says
ToSchema [a]is an openapi array ofToSchema a - https://hackage.haskell.org/package/openapi3-3.1.0/docs/src/Data.OpenApi.Internal.Schema.html#line-630 says
ToSchema (a,b)is implemented withgenericDeclareNamedSchema, which is where I stopped digging.
I expect this code was ported from / inspired by swagger2. The swagger (i.e. openapi2) spec is difficult to read, but I think it does support items being an array. However, openapi3 explicitly does not.
(re swagger/openapi2:
-
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#schemaObject says that
typeanditemsare as in the JSON Schema definition (with the minor change that when the JSON Schema spec says something must be "a JSON Schema", we should read "an openapi2 schema object" instead)
The JSON Schema (validation) spec is linked as https://datatracker.ietf.org/doc/html/draft-fge-json-schema-validation-00#page-9, which saysThe value of "items" MUST be either an object or an array
-
However it contradictarily seems not accepted at https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#itemsObject, which says that
itemsmust be anItems Object -
see also What part of Swagger spec describes SwaggerItemsArray? GetShopTV/swagger2#107 which is also confused on this point
)
The future
I wonder if it is worth adding a custom type error to explain why hetrogenous tuples / "complex" maps cannot be given a spec?
Longer term, it seems that openapi-3.1.0 is out which (if I read (the linked JSON Schema docs) correctly) brings back the ability for items to be an array, under the name prefixItems.
However, this does not seem well supported yet, for instance none of the validators above support it.