Here's the controller:
@Controller('products')
@UsePipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true, transform: true }))
export class ProductController {
constructor(
private readonly productService: ProductService,
) {}
@Get()
public async all(): Promise<ProductDto[]> {
return this.productService.all();
}
@Post()
@ApiResponse({type: ProductDto})
public async create(@Body() createProductDto: CreateProductDto): Promise<ProductDto> {
return this.productService.create(createProductDto);
}
}
Here's the service:
@Injectable()
export class ProductService {
constructor(
@InjectRepository(ProductEntity)
private readonly productRepository: Repository<ProductEntity>,
) {}
public async all(): Promise<ProductDto[]> {
return this.productRepository.find().then(products => products.map(p => new ProductDto().deserialize(p)));
}
public async create(createProductDto: CreateProductDto): Promise<ProductDto> {
const productEntity = new ProductEntity();
productEntity.image = createProductDto.image;
productEntity.title = createProductDto.title;
return productEntity.save().then(pe => new ProductDto().deserialize(pe));
}
}
And here is the ProductDto:
export class ProductDto implements Readonly<ProductDto>, IDeserializable<ProductDto, ProductEntity> {
@ApiProperty({name: 'id'})
@IsNumber()
private _id: number;
@ApiProperty({name: 'likes'})
@IsNumber()
private _likes: number;
@ApiProperty({name: 'title'})
@IsString()
private _title: string;
@ApiProperty({name: 'image'})
@IsString()
private _image: string;
public set id(val: number) {
this._id = val;
}
public get id(): number {
return this._id;
}
public set title(val: string) {
this._title = val;
}
public get title(): string {
return this._title;
}
public set image(val: string) {
this._image = val;
}
public get image(): string {
return this._image;
}
public set likes(val: number) {
this._likes = val;
}
public get likes(): number {
return this._likes;
}
public deserialize(data: ProductEntity): ProductDto {
this.image = data.image;
this.title = data.title;
this.likes = data.likes;
this.id = data.id;
return this;
}
}
The response contains underscores, I forgot how to remove them.
When I create a new product I get this:
{
"_image": "https://www.images.com/763267382.jpg",
"_title": "porsche",
"_likes": 0,
"_id": 26
}
but I want this:
{
"image": "https://www.images.com/763267382.jpg",
"title": "porsche",
"likes": 0,
"id": 26
}
How do I do that?
EDIT:
I could write a custom pipe that would trim them, but unless I'm very much mistaken there's a built-in trim or something, I don't remember.
CodePudding user response:
You can enable ClassSerializerInterceptor
by adding @UseInterceptors(ClassSerializerInterceptor)
to controller, and then use @Expose
decorator from class-transformer
package to change the name during serialization.
Here is what it looks like:
@Controller('products')
@UseInterceptors(ClassSerializerInterceptor)
@UsePipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true, transform: true }))
export class ProductController {
...
}
And ProductDto
:
import { Expose } from 'class-transformer';
export class ProductDto implements Readonly<ProductDto>, IDeserializable<ProductDto, ProductEntity> {
@Expose({ name: 'id' })
@ApiProperty({name: 'id'})
@IsNumber()
private _id: number;
@Expose({ name: 'likes' })
@ApiProperty({name: 'likes'})
@IsNumber()
private _likes: number;
@Expose({ name: 'title' })
@ApiProperty({name: 'title'})
@IsString()
private _title: string;
@Expose({ name: 'image' })
@ApiProperty({name: 'image'})
@IsString()
private _image: string;
...
You can find more information here.