swagger-typescript-api
swagger-typescript-api copied to clipboard
camelCase keys in models
Is it possible to generate camelCase keys in interfaces ?
Is it possible to generate camelCase keys in interfaces ?
Same question
Is it possible to generate camelCase keys in interfaces ?
Are keys in Swagger JSON in some other case? I guess this library just pulls what's defined there and doesn't do transformations, which seems like a good thing.
Depending on what you use, you might need to tell the swagger generator library to generate JSON definition with camelCase in mind. Where I work, we use .Net Core and Swashbuckle and we needed to tell Swashbuckle to generate properties as camelCase using DescribeAllParametersInCamelCase option. (https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/163#issuecomment-521934043)
I have solved it by onCreateComponent hook
Example of hook to pass it to generateApi method:
const camelCase = require('camelcase');
function onCreateComponent(component) {
if (component.rawTypeData.properties) {
component.rawTypeData.properties = mapEntries(component.rawTypeData.properties, ([propName, value]) => {
return [camelCase(propName), value];
});
}
if (component.rawTypeData.required && Array.isArray(component.rawTypeData.required)) {
component.rawTypeData.required = component.rawTypeData.required.map((propName) => camelCase(propName));
}
return component;
};
function mapEntries(obj, mapCallbackFn) {
return Object.fromEntries(Object.entries(obj).map(mapCallbackFn));
}
A little improvement for correct working with nested objects in schema
function onCreateComponent(component) {
function mapEntries(obj, mapCallbackFn) {
return Object.fromEntries(Object.entries(obj).map(mapCallbackFn));
}
function camelCaseProperties(obj) {
if (Array.isArray(obj)) {
return obj.map(camelCaseProperties);
} else if (typeof obj === 'object' && obj !== null) {
if (obj.properties) {
obj.properties = camelCaseProperties(obj.properties);
}
if (obj.items) {
obj.items = camelCaseProperties(obj.items);
}
['allOf', 'anyOf', 'oneOf'].forEach((keyword) => {
if (obj[keyword]) {
obj[keyword] = camelCaseProperties(obj[keyword]);
}
});
if (
obj.additionalProperties &&
typeof obj.additionalProperties === 'object'
) {
obj.additionalProperties = camelCaseProperties(
obj.additionalProperties
);
}
if (obj.required && Array.isArray(obj.required)) {
obj.required = obj.required.map(_.camelCase);
}
return mapEntries(obj, ([key, value]) => [
_.camelCase(key),
camelCaseProperties(value),
]);
} else {
return obj;
}
}
component.rawTypeData = camelCaseProperties(component.rawTypeData);
return component;
}
A little improvement for correct working with refs in schema.
Based on OpenAPI 3.0 (https://swagger.io/docs/specification/using-ref/), $ref key is used to create reference between shared schemas. By default, camelCase method from lodash will remove special character(s), so when we perform camel case on $ref it will result with ref. As a side effect, all nested objects will have any type instead of type that is referenced by schema.
function onCreateComponent(component) {
function mapEntries(object, mapCallbackFn) {
return Object.fromEntries(Object.entries(object).map(mapCallbackFn));
}
function camelCaseProperties(object) {
if (Array.isArray(object)) {
return object.map(camelCaseProperties);
} else if (typeof object === 'object' && object !== null) {
if (object.properties) {
object.properties = camelCaseProperties(object.properties);
}
if (object.items) {
object.items = camelCaseProperties(object.items);
}
['allOf', 'anyOf', 'oneOf'].forEach((keyword) => {
if (object[keyword]) {
object[keyword] = camelCaseProperties(object[keyword]);
}
});
if (
object.additionalProperties &&
typeof object.additionalProperties === 'object'
) {
object.additionalProperties = camelCaseProperties(
object.additionalProperties
);
}
if (object.required && Array.isArray(object.required)) {
object.required = object.required.map(_.camelCase);
}
return mapEntries(object, ([key, value]) => {
return [
/**
* Transforming key into camel case format needs to be done like follow
* because camelCase method from lodash removes special characters while
* performing transformation into camel case format.
* e.g., $ref key, that is introduced in OpenAPI 3.0,
* will be converted into ref if camelCase method itself is used
* @see https://swagger.io/docs/specification/using-ref/
*/
key.replace(/\w+/g, _.camelCase),
camelCaseProperties(value),
]
});
} else {
return object;
}
}
component.rawTypeData = camelCaseProperties(component.rawTypeData);
return component;
}
Thank everyone for the suggested onCreateComponent hook examples.
Still, when using them, there is a need to generate runtime transformations, otherwise the generated client will send data in camelCase but the server will not understand it as it expects data in snake_case. Fortunately, it is possible, as swagger-typescript-api allows to override its ejs templates.
Though, generation of runtime transformation always has its cons.
- Either we simply generate default request and response transformers that make dumb deep renaming of all data object properties into snake_case and, accordingly, camelCase. It can be faulty, as request body DTO types contain keys converted to camelCase, and in runtime we convert them back to snake_case. Applying "snake_case → camelCase → snake_case" transform will not always produce the initial value.
- Or we save and generate all "old name to new name" mappings and data convertion functions for every DTO, it is way too much generated boilerplate. It is hard to read and debug and can make the application slower.