如何在使用 Typegoose 获取数据时使用 class-transformer 序列化嵌套 js 响应?
Posted
技术标签:
【中文标题】如何在使用 Typegoose 获取数据时使用 class-transformer 序列化嵌套 js 响应?【英文标题】:How to serialize a nest js response with class-transformer while getting data with Typegoose? 【发布时间】:2020-06-16 21:58:02 【问题描述】:我一直在尝试使用 Typegoose 和 class-transformer 库来完成 Mongodb 的序列化部分的 NestJs 示例。 https://docs.nestjs.com/techniques/serialization 给出的示例仅显示了如何在 TypeORM 中使用序列化。我对 Typegoose 遵循了相同的过程。这是我到目前为止所尝试的。
// cat.domain.ts
import prop from '@typegoose/typegoose';
export class Cat
@prop()
name: string;
@prop()
age: number;
@prop()
breed: string;
// cats.service.ts
@Injectable()
export class CatsService
constructor(
@InjectModel(Cat) private readonly catModel: ReturnModelType<typeof Cat>,
)
findAll(): Observable<Cat[]>
return from(this.catModel.find().exec());
findOne(id: string): Observable<Cat>
return from(this.catModel.findById(id).exec());
...
// cat.response.ts
import ObjectId from 'mongodb';
import Exclude, Transform from 'class-transformer';
export class CatResponse
@Transform(value => value.toString(), toPlainOnly: true )
_id?: ObjectId;
name: string;
age: number;
@Exclude()
breed: string;
constructor(partial: Partial<CatResponse>)
Object.assign(this, partial);
// cats.controller.ts
@Controller('cats')
@UseInterceptors(ClassSerializerInterceptor)
export class CatsController
constructor(private readonly catsService: CatsService)
@Get()
findAll(): Observable<CatResponse[]>
return this.catsService.findAll();
@Get(':id')
findOne(@Param() params: FindOneParamsDto): Observable<CatResponse>
return this.catsService.findOne(params.id);
...
我尝试使用 id 在 Get() 上运行 API 调用,但 breed
没有被排除在响应之外,而是得到了以下响应。
"$__":
"strictMode": true,
"selected": ,
"getters": ,
"_id":
"_bsontype": "ObjectID",
"id":
"type": "Buffer",
"data": [
94,
93,
76,
66,
116,
204,
248,
112,
147,
216,
167,
205
]
,
"wasPopulated": false,
"activePaths":
"paths":
"_id": "init",
"name": "init",
"age": "init",
"breed": "init",
"__v": "init"
,
"states":
"ignore": ,
"default": ,
"init":
"_id": true,
"name": true,
"age": true,
"breed": true,
"__v": true
,
"modify": ,
"require":
,
"stateNames": [
"require",
"modify",
"init",
"default",
"ignore"
]
,
"pathsToScopes": ,
"cachedRequired": ,
"$setCalled": [],
"emitter":
"_events": ,
"_eventsCount": 0,
"_maxListeners": 0
,
"$options":
"skipId": true,
"isNew": false,
"willInit": true
,
"isNew": false,
"_doc":
"_id":
"_bsontype": "ObjectID",
"id":
"type": "Buffer",
"data": [
94,
93,
76,
66,
116,
204,
248,
112,
147,
216,
167,
205
]
,
"name": "Sylver",
"age": 14,
"breed": "Persian Cat",
"__v": 0
,
"$locals": ,
"$op": null,
"$init": true
谁能帮我正确地序列化响应?
【问题讨论】:
【参考方案1】:更新: class-transformer 现在可以与 typegoose 一起正常工作,look here for the documentation on how to use it
this is an known issue (#108)、typegoose (& mongoose) 与 class-transformer/class-validator 不兼容 这是因为 typegoose 需要将类转换为模式,而 mongoose 会将其编译为模型(不再是类)
【讨论】:
你会如何建议我从我的回复中排除项目?我正在考虑做一些类似的事情,比如创建一个转换拦截器和一个自定义装饰器,并检查拦截器中的装饰器,但这似乎需要做很多工作,而且我还没有那么有经验。有更简单的方法吗? 当它是像“password”这样的值时,您可以将“select: false”设置为@prop
选项,默认情况下它不包含在任何查询中,除非再次明确选择它,否则转换它到POJO(通过.toJSON
或.lean
)并过滤掉您不想要的任何内容(黑名单/白名单)
如何在使用 MONGOOSE 获取数据的同时使用 class-transformer 序列化嵌套 js 响应?
答案中的链接显示“404 Not found”。
@RollerCosta,我已经更新了链接【参考方案2】:
这里有一个解决方法:
// cats.controller.ts
...
import classToPlain from "class-transformer";
...
@Controller('cats')
@UseInterceptors(ClassSerializerInterceptor)
export class CatsController
constructor(private readonly catsService: CatsService)
@Get()
findAll(): Observable<CatResponse[]>
const cats = this.catsService.findAll();
// transforming the Model to CatResponse class...
const catResponses = cats.map(cat => classToPlain(new CatResponse(cat.toJSON())))
return catResponses;
@Get(':id')
findOne(@Param() params: FindOneParamsDto): Observable<CatResponse>
const cat = this.catsService.findOne(params.id);
const catResponse = classToPlain(new CatResponse(cat.toJSON()));
return
...
希望对您有所帮助。
【讨论】:
以上是关于如何在使用 Typegoose 获取数据时使用 class-transformer 序列化嵌套 js 响应?的主要内容,如果未能解决你的问题,请参考以下文章
仅调用 Typegoose 进行保存操作时,钩子在 updateOne 上不起作用
Mongoose / typegoose 根据开始和结束索引获取数组