Third pattern of our series looking at how we could improve the OpenAPI specification for the purpose of code generation. Today we’ll look at type and formats which are crucial to generate accurate and useful clients.
components: schemas: Model: type: object properties: noType: properties: subProp: type: string impossibleCombination: type: string format: int32
In the snippet above, for the first example properties are defined, which hints the type should be an object, but the type property is not set to object. The second example is an impossible combination that’s allowed because the JSON schema specification does not mandate any validation of the format property. If we dive deeper into this aspect, we find that a lot of type combinations are considered valid by conventions, but there’s no central registry to date, although OpenAPI is working on one:
|string||commonmark, html, date-time, duration, date, time, base64url, uuid, ""|
|string (not supported by kiota)||email, idn-email, hostname, idn-hostname, ipv4, ipv6, uri, uri-reference, iri, iri-reference, uri-template, json-pointer, relative-json-pointer, regex|
|number||float, double, decimal, int32, int64, int8, uint8, ""|
|integer||int32, int64, int8, uint8|
|""||byte, binary (technically invalid according to the JSON schema spec)|
From this list we can already notice there is overlap between integer and number.
This one is not going to be an easy fix, but we can improve the situation. We should start by removing integer from the options valid for type and add the well known formats options in the JSON schema core vocabulary. This is going to be breaking change for some descriptions. We could even introduce a “simple” format value for string, and outlaw not having a format for string, and number. We might also want to introduce a “raw” type to support the byte and binary formats. If we did all of that, there would be no more valid case for not having the type property set. Linters will be a great help if they could add the following rules:
- Error when the format property is used while the type property is any of object, array, null, Boolean, file.
- Error when using the integer type.
- Error when a known format is used with a type it doesn’t belong to.
- Warn when a type that supports a format does not have a format described.
- Error when the type property is not set.