Enums Mappings in OpenAPI

Ikechi Michael
2 min readNov 7, 2024

--

OpenAPI does not directly support mapping enum keys to values, so if we had an C# enum:

enum Direction {
Up = 0;
Down = 1;
Left = 2;
Right = 3;
}

The equivalent OpenAPI json file would be missing the enum keys. To supply them, we can use the x-enum-varnames extension. This extension allows us to provide additional metadata for our enums, such as the variable names used in our code.

Here’s how we can represent the Direction enum from our C# example in an OpenAPI JSON file:

{
"components": {
"schemas": {
"Direction": {
"type": "integer",
"enum": [0, 1, 2, 3],
"x-enum-varnames": ["Up", "Down", "Left", "Right"]
}
}
}
}

Explanation

  • type: The type is set to integer because the enum values in C# are integers.
  • enum: This array contains the possible integer values of the enum.
  • x-enum-varnames: This is a custom extension that lists the variable names corresponding to each enum value. This extension is not part of the official OpenAPI specification but is commonly used to provide additional context or metadata.

Conclusion

While OpenAPI does not natively support key-value mappings for enums, using extensions like x-enum-varnames provides a flexible way to include additional metadata.

Client generators like openapi-generator-cli can use the extension to provide a key<>value mapping for the generated enums.

And even when a tool doesn’t directly support it, we could do some post-processing to generate the enum types:

const extractEnums = (openApiDoc: OpenAPIObject) => {
const schemas = openApiDoc.components?.schemas;
if (!schemas) return {};
const enumConstants = {} as Record<string, string>;
for (const [key, schema] of Object.entries(schemas)) {
if ("enum" in schema && "x-enum-varnames" in schema) {
const enumValues = schema.enum as number[];
const enumNames = schema["x-enum-varnames"] as string[];
const enumMap = enumNames.reduce((acc, name, index) => {
acc[name] = enumValues[index];
return acc;
}, {} as Record<string, number>);
const enumKey = key.replaceAll(".", "_");
enumConstants[key] = `
export const ${enumKey} = {
${enumNames.map((name) => `${name}: ${enumMap[name]}`).join(",\n")}
} as const;
`;
}
}
return `export namespace enums {
${Object.values(enumConstants).join("\n")}
}`;
}

--

--

Ikechi Michael
Ikechi Michael

Written by Ikechi Michael

I’ve learned I don’t know anything. I've also learned that people will pay for what I know. Maybe that's why they never pay.

No responses yet