SerializeInterceptor
Intercepts request/response data and deserializes/serializes to DTO format.
- For requests: converts snake_case to camelCase (you can use camelCase in your DTO while accepting snake_case JSON input)
- For responses: converts camelCase to snake_case (you can use camelCase in your DTO while sending snake_case JSON to clients)
In summary:
- JSON layer: snake_case
- Model layer: camelCase
This conversion works for nested objects as well.
When a client sends the following data:
{
"name": "nolleh",
"email": "[email protected]",
"some_snake_data": "hello world",
"live": {
"country": "South Korea",
"city": "Seongnam",
"some_snake_data": "hello world2"
}
}
You can access it in your code as:
class LiveDto {
country,
city,
someSnakeData
}
class MyDto {
name,
email,
someSnakeData,
live,
}
Add this to your main code. You can find the complete example at:
import { SerializeInterceptor } from 'serialize-interceptor';
import { NestFactory } from '@nestjs/core';
...
const app = await NestFactory.create(AppModule);
/** use our interceptor **/
app.useGlobalInterceptors(new SerializeInterceptor);
// @since 1.1.5
// if you want to customize serializer, then put your strategy.
// const strategy: Strategy = {
// in: DEFAULT_STRATEGY.in,
// out: (v) => {
// // return 'test-swallow up!';
// return snakeToCamel(v)
// },
// };
// app.useGlobalInterceptors(new SerializeInterceptor(strategy));
OR in module
@Module({
controllers: [AppController],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: SerializeInterceptor,
},
/** @since 1.1.5
// if you want to customize serializer, then put your strategy.
{
provide: Strategy,
useFactory: () => ({
in: DEFAULT_STRATEGY.in,
out: (v) => {
// return 'test-swallow up!';
// your custom func. the default for 'out' is.. snakeToCamel.
return snakeToCamel(v);
},
}),
},
**/
})
export class AppModule {}
You can define your own serialization strategy as shown in the snippets above.
SerializeInterceptor provides classes to help you define your own strategy:
/** Since the regenerated value's fields differ from the original,
* it's challenging to declare the return type.
* The input type is also not meaningful.
*
* in: request layer (default: snakeToCamel),
* out: response layer (default: camelToSnake).
*
* i.e. const DEFAULT_STRATEGY: Strategy = { in: snakeToCamel, out: camelToSnake };
*/
export class Strategy {
in: (value: any) => any;
out: (value: any) => any;
}
export const DEFAULT_STRATEGY: Strategy = {
in: snakeToCamel,
out: camelToSnake,
};
As shown above, implement the Strategy
class with in/out functions,
and provide it as a constructor (either through injection or by creating a new instance).
The interceptor will then work according to your definition.
🤔 Do you need a specific strategy that you'd like to see provided by this library?
Let me know!
Available strategies:
Name | Description | Remark (side effect) | Default |
---|---|---|---|
snakeToCamel | snake -> camel | dash(-, kebab) also converted to camel | default for in (request) |
camelToSnake | camel -> snake | starting with capital (pascal) also converted to snake | default for out (response) |
kebabToCamel | kebab -> camel | No side effects | |
camelToKebab | camel -> kebab | No side effects | |
camelTosnake2 | camel ↔ snake | without kebab side effects | |
snakeToCamel2 | snake -> camel | without kebab side effects |
While these side effects can be useful in many cases, they might not be desirable in all situations.
NestJS
Designed for NestJS interceptor.