-
Notifications
You must be signed in to change notification settings - Fork 53
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 schemas generated for tuples and (some) Map
s
#31
Comments
Hi! Thanks for such a detailed report. Unfortunately, OAS 3.0 dropped support for tuple-like arrays, leaving only heterogeneous ones:
I've however decided to leave the relevant code in Thanks for the link to OAS 3.1, I will look at it. However, as far as I can tell, 3.0 remains the official version for now, so I'm not sure if it makes sense to migrate to 3.1. Will swagger-ui support it, for example? |
I think 3.1 is officially released, according to https://github.com/OAI/OpenAPI-Specification#current-version---310 and https://www.openapis.org/ (which has a big image saying "3.1.0 released").
I don't know much on this front, I'm afraid. My impression is that tool support seems to be lacking at the moment, so I suspect it may not be worth the effort yet (I hope this will change in the future!). Swagger-ui in particular does not support 3.1 yet; there is an open issue swagger-api/swagger-ui#5891, though there doesn't seem to be much activity on this. I have seen that 3.1 support is in the "short-term roadmap" for swagger-api/swagger-parser#1535 (comment), but I don't know an ETA. |
I'm reviving this issue, because I think I found a solution for the tuple case. This tuple representation does not validate: {
"minItems": 2,
"items": [
{
"type": "string"
},
{
"$ref": "#/components/schemas/Dog"
}
],
"maxItems": 2,
"type": "array"
} however this does: {
"minItems": 2,
"items": {
"oneOf": [
{ "type": "string" },
{
"$ref": "#/components/schemas/Dog"
}
]
},
"maxItems": 2,
"type": "array"
} I'm not sure if this means that the schemas are applied to each array item in order though. |
{
"minItems": 2,
"items": {
"oneOf": [
{ "type": "string" },
{
"$ref": "#/components/schemas/Dog"
}
]
},
"maxItems": 2,
"type": "array"
} @JohanWinther sadly, this one defines an array of any length, each item of which can be either string or There is really no way to specify tuples in the OpenAPI 3.0 spec. |
openapi-generator chokes on these as it abides by OAS 3.0.
Would be nice if we could merge #69 and resolve this |
Workaround for biocad#31 If the tuples has homogeneous types, the generated schema is strict. On the other hand if there are heterogeneous types, the schema is not very strict because the order in which the types must come is not specified. Also, I had to use anyOf instead of oneOf because for example the int in (Int, Float) matches both Integer and Number. Finally, special care had to be taken to handle nullables.
Workaround for biocad#31 If the tuples has homogeneous types, the generated schema is strict. On the other hand if there are heterogeneous types, the schema is not very strict because the order in which the types must come is not specified. Also, I had to use anyOf instead of oneOf because for example the int in (Int, Float) matches both Integer and Number. Finally, special care had to be taken to handle nullables.
Workaround for biocad#31 If the tuples has homogeneous types, the generated schema is strict. On the other hand if there are heterogeneous types, the schema is not very strict because the order in which the types must come is not specified. Also, I had to use anyOf instead of oneOf because for example the int in (Int, Float) matches both Integer and Number. Finally, special care had to be taken to handle nullables.
Workaround for biocad#31 If the tuples has homogeneous types, the generated schema is strict. On the other hand if there are heterogeneous types, the schema is not very strict because the order in which the types must come is not specified. Also, I had to use anyOf instead of oneOf because for example the int in (Int, Float) matches both Integer and Number. Finally, special care had to be taken to handle nullables.
If anyone is stuck using openapi-generator because of this, I implemented the above suggested workaround in novainsilico#2 Note that I used I also made sure to add Finally, I also re-implemented #46 with some tests added. While I don't expect any interest to merge the first commit, let me know if you would like me to open a PR for the second one. |
@brprice FWIW, the problem here is actually slightly more general than the current thread title suggests, as it also applies to any sum type where a constructor has multiple fields, as Aeson also represents these as a two-element array, just as for tuples. Also, to save others misreading the previous few comments as I did, the "above suggested workaround" in #31 (comment) refers to #31 (comment), which as pointed out in #31 (comment), is far from a universally-applicable workaround. It just uses a much looser type: |
Workaround for biocad#31 If the tuples has homogeneous types, the generated schema is strict. On the other hand if there are heterogeneous types, the schema is not very strict because the order in which the types must come is not specified. Also, I had to use anyOf instead of oneOf because for example the int in (Int, Float) matches both Integer and Number. Finally, special care had to be taken to handle nullables.
Workaround for biocad#31 If the tuples has homogeneous types, the generated schema is strict. On the other hand if there are heterogeneous types, the schema is not very strict because the order in which the types must come is not specified. Also, I had to use anyOf instead of oneOf because for example the int in (Int, Float) matches both Integer and Number. Finally, special care had to be taken to handle nullables.
Description
It seems we generate invalid schemas for all tuples and
Map
s with "complex" keys (those thataeson
'stoJSONKey
isToJSONKeyValue
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 toAccording to the OpenAPI3 spec, the
items
field 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)
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
ToSchema (Map k v) = ToSchema [(k,v)]
for "complex" keysToSchema [a]
is an openapi array ofToSchema a
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
type
anditems
are 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
items
must 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 nameprefixItems
.However, this does not seem well supported yet, for instance none of the validators above support it.
The text was updated successfully, but these errors were encountered: