Crud: Serialization for getMany not wokring properly

Created on 2 Feb 2020  路  2Comments  路  Source: nestjsx/crud

Hello!

First of all, thanks for the awesome job you are doing with this project.

As far as I understand from these docs:
https://github.com/nestjsx/crud/wiki/Controllers#serialize
https://github.com/nestjsx/crud/wiki/Controllers#response-serialization
I can adjust the shape of the resposne from a CRUD controller with DTO classes.

I'm decorating my controller with the @Crud decorator, that has the serialize option specified like this:

import {Crud, CrudController} from '@nestjsx/crud';
import { Controller } from '@nestjs/common';
import {Post} from './post.entity';
import {PostsService} from './posts.service';
import {GetManyPostsDto} from './dto/get-many-posts.dto';
import {GetOnePostDto} from './dto/get-one-post.dto';

@Crud({
    model: {
        type: Post,
    },
    routes: {
        only: ['getOneBase', 'getManyBase'],
    },
    serialize: {
        getMany: GetManyPostsDto,
        get: GetOnePostDto,
    }
})
@Controller('posts')
export class PostsController implements CrudController<Post> {
    constructor(public service: PostsService) {}
}

My GetManyPostsDto class looks like this:

import {Exclude} from 'class-transformer';

export class GetManyPostsDto {
    id: string;

    title: string;

    @Exclude()
    text: string;
}

The GetOnePostDto looks like this:

export class GetOnePostDto {
    id: string;

    title: string;

    text: string;
}

What I expect is when I'm making a GET request to the /posts route, it should return posts without the text field. However, my tests show that the field is still there.

I've created a small repo illustrating this:
https://github.com/NikitaKrasavtsev/nestjsx-crud-bug

Most helpful comment

This is a misconception and a easy to get wrong (I struggled with this too).
The getMany option is not applied to objects of the list, but to the response itself.
You can use the getMany serializer to serialize the pagination response, for example to only return data and count:

@Exclude()
class ManyDTO {
    @Expose()
    data: any[];

    @Expose()
    count: number;
}

If you want to apply a serializer to the data is has to be nested like this:

@Exclude()
class FeedListDTO {
    @Expose()
    id: string;
}
@Exclude()
class ManyDTO {
    @Expose()
    count: number;

    @Expose()
    @Type(() => FeedListDTO)
    data: FeedListDTO[];
}

It's a bit cumbersome but gets the job done if alwaysPaginate=true.
I think this should be redesigned, where the getMany serializer is applied to single objects instead of the whole response.

All 2 comments

It may be related to the use of the get DTO instead of getMany in serialize function.
Source

Also, it doesn't seem to handle paginated responses.

This is a misconception and a easy to get wrong (I struggled with this too).
The getMany option is not applied to objects of the list, but to the response itself.
You can use the getMany serializer to serialize the pagination response, for example to only return data and count:

@Exclude()
class ManyDTO {
    @Expose()
    data: any[];

    @Expose()
    count: number;
}

If you want to apply a serializer to the data is has to be nested like this:

@Exclude()
class FeedListDTO {
    @Expose()
    id: string;
}
@Exclude()
class ManyDTO {
    @Expose()
    count: number;

    @Expose()
    @Type(() => FeedListDTO)
    data: FeedListDTO[];
}

It's a bit cumbersome but gets the job done if alwaysPaginate=true.
I think this should be redesigned, where the getMany serializer is applied to single objects instead of the whole response.

Was this page helpful?
0 / 5 - 0 ratings