First pattern of our series: enumerations. They are essential to any programing language to describe a discrete set of options. Consider the following examples:
components: schemas: Model: type: object properties: enumString: type: string enum: - value1 - value2 enumInteger: type: integer enum: - 1 - 2 enumBoolean: type: boolean enum: - true - false
EnumString describes two possible values, however it’s missing a lot of information:
- We can’t specify a different serialization value from the symbol.
- We can’t specify a description which would be helpful to developers who discover the API surface through a client.
EnumInteger describes an integer type enumeration, where each option is a number. While this is a valid scenario, it makes code generation harder as most programming languages don’t accept numbers or strings starting with numbers as valid symbols which leads to compilation errors. Additionally, if the enumeration values are powers of 2, the enumeration is flaggable (supports compounded values through a bitwise or). But we have no way to convey this information.
EnumBoolean is a Boolean type enumeration. In my opinion, it is completely useless. A boolean is an enumeration that can only hold two possible values.
Interestingly enough, autorest already has an extension defined to bridge some of those gaps and I believe the solution should be based on that early work. First, we need to introduce the placeholder for the missing information, and if possible, avoid breaking existing descriptions out there. The enum property should be extended in the OpenAPI JSON schema vocabulary to be an array of symbols (like it is today) or an object with the following properties:
- Items, array of objects (value, name, description).
- Composable (Boolean).
Second, we must encourage people to do the right thing when describing their APIs and I think linting tools like spectral should introduce the following rules:
- Error if the description contains an enum of type Boolean, just use a Boolean.
- Error if the description contains a number enum item without the name property we introduced above.
- Error if the description contains a composable enum, but the values are not powers of 2.
- Warning if enum items don’t have descriptions.
The resulting enum would look like this:
components: schemas: Model: type: object properties: enumInteger: type: integer default: 1 enum: - 1 - 2 x-ms-enum: name: EnumInteger flags: true # this doesn't exist in the extension today values: - value: 1 name: Value1 description: Value 1 - value: 2 name: Value2 description: Value 2