Skip to content

Commit

Permalink
fix(json-mapper): fix generic serialization
Browse files Browse the repository at this point in the history
Closes: #2478
  • Loading branch information
Romakita committed Oct 26, 2023
1 parent 81f3bb8 commit afc37c5
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 2 deletions.
8 changes: 7 additions & 1 deletion packages/specs/json-mapper/src/domain/JsonSerializer.ts
Expand Up @@ -180,15 +180,21 @@ export class JsonSerializer extends JsonMapperCompiler<JsonSerializerOptions> {
}

private getPropertyFiller(propertyStore: JsonPropertyStore, key: string, groups: false | string[], formatOpts: any) {
const isGeneric = propertyStore.itemSchema.isGeneric;

if (propertyStore.isCollection) {
const type = propertyStore.getBestType();

const nestedMapper = this.compile(type, groups);
const nestedMapper = isGeneric ? {id: ""} : this.compile(type, groups);

return (writer: Writer) =>
writer.callMapper(nameOf(propertyStore.collectionType), varKey(key), `id: '${nestedMapper.id}'`, formatOpts);
}

if (isGeneric) {
return (writer: Writer) => writer.set(varKey(key), `compileAndMap(${varKey(key)}, options)`);
}

const type = propertyStore.getBestType();
const nestedMapper = this.compile(type, groups);

Expand Down
@@ -1,5 +1,21 @@
import {boolean, date, GenericOf, Generics, number, Property, string} from "@tsed/schema";
import {Controller} from "@tsed/di";
import {
boolean,
CollectionOf,
date,
GenericOf,
Generics,
Get,
Ignore,
JsonEntityStore,
number,
Property,
Required,
Returns,
string
} from "@tsed/schema";
import {deserialize} from "../../src/utils/deserialize";
import {serialize} from "../../src/utils/serialize";

describe("Generics", () => {
describe("using Functional api", () => {
Expand Down Expand Up @@ -268,4 +284,133 @@ describe("Generics", () => {
});
});
});

describe("Pagination", () => {
it("should serialize correctly the return object from controller (generic array)", () => {
@Generics("T")
class Pagination<T> {
@CollectionOf("T")
@Required()
items: T[];

@Required()
totalCount: number;

constructor(partial: Partial<Pagination<T>>) {
Object.assign(this, partial);
}
}

class TestEntity {
@Property("id")
public _id: string;

@Property()
name: string;

@Property()
@Ignore()
secret: string;
}

@Controller("/hello-world")
class HelloWorldController {
constructor() {}

@Get("/")
@Returns(200, Pagination).Of(TestEntity)
get() {}
}

const endpoint = JsonEntityStore.fromMethod(HelloWorldController, "get");

const responseOpts = endpoint.getResponseOptions(200, {});

const item = new TestEntity();
item._id = "64f05e452ecc156cff3b58f4";
item.name = "Test";
item.secret = "top";

const paginated = new Pagination({items: [item], totalCount: 1});

const result = serialize(paginated, {
useAlias: true,
additionalProperties: false,
...responseOpts,
endpoint: true
});

expect(result).toEqual({
items: [
{
_id: "64f05e452ecc156cff3b58f4",
name: "Test"
}
],
totalCount: 1
});
});
it("should serialize correctly the return object from controller (generic item)", () => {
@Generics("T")
class Pagination<T> {
@Property("T")
@Required()
item: T;

@Required()
totalCount: number;

constructor(partial: Partial<Pagination<T>>) {
Object.assign(this, partial);
}
}

class TestEntity {
@Property("id")
public _id: string;

@Property()
name: string;

@Property()
@Ignore()
secret: string;
}

@Controller("/hello-world")
class HelloWorldController {
constructor() {}

@Get("/")
@Returns(200, Pagination).Of(TestEntity)
get() {}
}

const endpoint = JsonEntityStore.fromMethod(HelloWorldController, "get");

const responseOpts = endpoint.getResponseOptions(200, {});

const item = new TestEntity();
item._id = "64f05e452ecc156cff3b58f4";
item.name = "Test";
item.secret = "top";

const paginated = new Pagination({item: item, totalCount: 1});

const result = serialize(paginated, {
useAlias: true,
additionalProperties: false,
...responseOpts,
endpoint: true
});

expect(result).toEqual({
item: {
_id: "64f05e452ecc156cff3b58f4",
name: "Test"
},
totalCount: 1
});
});
});
});

0 comments on commit afc37c5

Please sign in to comment.