admin管理员组文章数量:1323023
I started to work in a new NestJs project but I'm facing an issue when I try to implement serialization. I want to implement serialization to transform objects before they gets sent in a network response. My project was working correctly but when I tried to implement ClassSerializerInterceptor in my controller I got the following error:
[Nest] 27010 - 12/23/2019, 8:20:53 PM [ExceptionsHandler] Maximum call stack size exceeded +29851ms
RangeError: Maximum call stack size exceeded
at Object.Console.<puted> (internal/console/constructor.js:241:9)
at Object.log (internal/console/constructor.js:282:26)
at Object.consoleCall (<anonymous>)
at _loop_1 (/path/to/my/project/node_modules/class-transformer/TransformOperationExecutor.js:146:47)
I started to work in a new NestJs project but I'm facing an issue when I try to implement serialization. I want to implement serialization to transform objects before they gets sent in a network response. My project was working correctly but when I tried to implement ClassSerializerInterceptor in my controller I got the following error:
[Nest] 27010 - 12/23/2019, 8:20:53 PM [ExceptionsHandler] Maximum call stack size exceeded +29851ms
RangeError: Maximum call stack size exceeded
at Object.Console.<puted> (internal/console/constructor.js:241:9)
at Object.log (internal/console/constructor.js:282:26)
at Object.consoleCall (<anonymous>)
at _loop_1 (/path/to/my/project/node_modules/class-transformer/TransformOperationExecutor.js:146:47)
I changed the scope of ClassSerializerInterceptor to solve the problem but the error persists. According to the documentation, I need to use the interceptor in a controller and use the corresponding decorators in an entity to implement serialization. My implementation of serialization is the following:
billing-statement.controller.ts
import { ClassSerializerInterceptor, Controller, Get, Query, UseInterceptors } from '@nestjs/mon';
import { BillingStatementService } from './billing-statement.service';
import { BillingStatementDto } from './billing-statement.dto';
import { BillingStatement } from './billing-statement.entity';
@Controller('billing-statement')
export class BillingStatementController {
constructor(private readonly billingStatementService: BillingStatementService) {}
@Get()
@UseInterceptors(ClassSerializerInterceptor)
async getBillingStatement(
@Query() query: BillingStatementDto,
): Promise<BillingStatement> {
return this.billingStatementService.findBillingStatementByUser(+query.id);
}
}
billing-statement.entity.ts
import { AutoIncrement, BelongsTo, Column, ForeignKey, HasMany, Model, PrimaryKey, Table } from 'sequelize-typescript';
import { User } from '../users/user.entity';
import { Payment } from './payment.entity';
import { Exclude } from 'class-transformer';
@Table({
tableName: 'billing_statement_tbl',
timestamps: false,
})
export class BillingStatement extends Model<BillingStatement> {
@AutoIncrement
@PrimaryKey
@Column({field: 'billing_statement_id_pk'})
id: number;
@Column
currency: string;
@Column({field: 'total_amount'})
totalAmount: number;
@Exclude()
@Column({field: 'contract_start'})
contractStart: Date;
@Exclude()
@Column({field: 'contract_end'})
contractEnd: Date;
@HasMany(() => Payment)
payments: Payment[];
}
I don't know what I'm doing wrong or what is the source of the error.
Share Improve this question asked Dec 24, 2019 at 2:52 ELopezELopez 651 gold badge1 silver badge8 bronze badges2 Answers
Reset to default 4From what I've seen so far, two things came to my mind.
- Extend use of
class-transformer
and make use ofclass-validator
within entity class in order to exclude the whole class' properties and only expose the wanted ones in your resulting serialized object.
Code would like this:
billing-statement.entity.ts
import { AutoIncrement, BelongsTo, Column, ForeignKey, HasMany, Model, PrimaryKey, Table } from 'sequelize-typescript';
import { User } from '../users/user.entity';
import { Payment } from './payment.entity';
import { Exclude, Expose, Type } from 'class-transformer';
import { IsArray, IsNumber, IsString } from 'class-validator';
@Exclude()
@Table({
tableName: 'billing_statement_tbl',
timestamps: false,
})
export class BillingStatement extends Model<BillingStatement> {
@AutoIncrement
@PrimaryKey
@Column({field: 'billing_statement_id_pk'})
@Expose()
@IsNumber()
id: number;
@Column
@Expose()
@IsString()
currency: string;
@Column({field: 'total_amount'})
@Expose()
@IsNumber()
totalAmount: number;
@Column({field: 'contract_start'})
contractStart: Date;
@Column({field: 'contract_end'})
contractEnd: Date;
@HasMany(() => Payment)
@IsArray()
@Expose()
@Type(() => Payment)
payments: Payment[];
}
- Another way would be to split your entity definition from the returned dto definition, in that way you can extend the definition of your entity, plus or minus wanted and unwanted properties in the returned dto. E.g, let's say you have named your response dto
BillingStatementResponseDto
, you would use this one in your controller response type.BillingStatementResponseDto
could contain external api object's attributes (fetch from some external api for exampleà, some of your entity attributes and some of the ining request dto's properties as well. You would also extend use ofclass-transformer
and make use ofclass-validator
like in 1st advice above in theBillingStatementResponseDto
definition.
Code would look like this:
billing-statement.entity.ts (remains the same, without class-transformer stuff)
import { AutoIncrement, BelongsTo, Column, ForeignKey, HasMany, Model, PrimaryKey, Table } from 'sequelize-typescript';
import { User } from '../users/user.entity';
import { Payment } from './payment.entity';
@Table({
tableName: 'billing_statement_tbl',
timestamps: false,
})
export class BillingStatement extends Model<BillingStatement> {
@AutoIncrement
@PrimaryKey
@Column({field: 'billing_statement_id_pk'})
id: number;
@Column
currency: string;
@Column({field: 'total_amount'})
totalAmount: number;
@Column({field: 'contract_start'})
contractStart: Date;
@Column({field: 'contract_end'})
contractEnd: Date;
@HasMany(() => Payment)
payments: Payment[];
}
billing-statement-response.dto.ts (new file definition for your targeted returned object, with use of class-transformer
and class-validator
) - to be imported and used in your controller
import { Exclude, Expose, Type } from 'class-transformer';
import { IsArray, IsNumber, IsString, ValidateNested } from 'class-validator';
@Exclude()
export class BillingStatementResponseDto {
@Expose()
@IsNumber()
id: number;
@Expose()
@IsString()
currency: string;
@Expose()
@IsNumber()
totalAmount: number;
@IsArray()
@ValidateNested()
@Expose()
@Type(() => Payment)
payments: Payment[];
}
billing-statement.controller.ts
import { ClassSerializerInterceptor, Controller, Get, Query, UseInterceptors } from '@nestjs/mon';
import { BillingStatementService } from './billing-statement.service';
import { BillingStatementDto } from './billing-statement.dto';
import { BillingStatementResponseDto } from './billing-statement-response.dto'; // <= import your newly defined dto
@Controller('billing-statement')
export class BillingStatementController {
constructor(private readonly billingStatementService: BillingStatementService) {}
@Get()
@UseInterceptors(ClassSerializerInterceptor)
async getBillingStatement(
@Query() query: BillingStatementDto,
): Promise<BillingStatementResponseDto> { // <= here you go for the use of BillingStatementResponseDto
return this.billingStatementService.findBillingStatementByUser(+query.id);
}
}
IMHO, second solution would be better in terms of layers separation, flexibility, modularity and maintainability :)
Let me know if it helps ;)
Based on the error message, I think you have a circular reference issue. Just ment out the other objects that your billing_statement object is referring to , and then try again. If that is the reason you are getting this error, you should remove reference from child objects to the parent object or try not to serialize those references.
Best of luck.
本文标签: javascriptHow to properly set up serialization with NestJSStack Overflow
版权声明:本文标题:javascript - How to properly set up serialization with NestJS? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742104181a2420943.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论