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
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:
)
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.
Description
It seems we generate invalid schemas for all tuples and
Maps with "complex" keys (those thataeson'stoJSONKeyisToJSONKeyValueand thus the map is encoded as an array of key-value pairs, rather than as a json object).This is because
Map k vis encoded the same as[(k,v)]for these keys, and(k,v)generates a schema similar toAccording to the OpenAPI3 spec, the
itemsfield must not be 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
(See also this gist for the generated schema, and a few other examples)
by https://validator.swagger.io/validator
The output of this is rejected as
and https://editor.swagger.io/ and https://openapi-generator.tech/ (both of which give more useful error messages)
The code that constructs these specs
ToSchema (Map k v) = ToSchema [(k,v)]for "complex" keysToSchema [a]is an openapi array ofToSchema aToSchema (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
itemsbeing 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 says
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 Objectsee 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
itemsto be an array, under the nameprefixItems.However, this does not seem well supported yet, for instance none of the validators above support it.