Skip to content

Commit 6f64c86

Browse files
committed
Add nested query params json support
1 parent 34cb2e4 commit 6f64c86

File tree

3 files changed

+44
-10
lines changed

3 files changed

+44
-10
lines changed

src/ActionParameterHandler.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,21 @@ export class ActionParameterHandler<T extends BaseDriver> {
111111

112112
// if param value is an object and param type match, normalize its string properties
113113
if (typeof value === "object" && ["queries", "headers", "params", "cookies"].some(paramType => paramType === param.type)) {
114-
Object.keys(value).map(key => {
114+
await Promise.all(Object.keys(value).map(async key => {
115115
const keyValue = value[key];
116116
if (typeof keyValue === "string") {
117117
const ParamType: Function|undefined = Reflect.getMetadata("design:type", param.targetType.prototype, key);
118118
if (ParamType) {
119-
const typeString = ParamType.name.toLowerCase(); // reflected type is always constructor-like?
120-
value[key] = this.normalizeStringValue(keyValue, param.name, typeString);
119+
const typeString = ParamType.name.toLowerCase();
120+
value[key] = await this.normalizeParamValue(keyValue, {
121+
...param,
122+
name: key,
123+
targetType: ParamType,
124+
targetName: typeString,
125+
});
121126
}
122127
}
123-
});
128+
}));
124129
}
125130
// if value is a string, normalize it to demanded type
126131
else if (typeof value === "string") {
@@ -137,9 +142,9 @@ export class ActionParameterHandler<T extends BaseDriver> {
137142
if ((["number", "string", "boolean"].indexOf(param.targetName) === -1)
138143
&& (param.parse || param.isTargetObject)
139144
) {
140-
value = this.parseValue(value, param);
141-
value = this.transformValue(value, param);
142-
value = this.validateValue(value, param); // note this one can return promise
145+
value = this.parseValue(value, param);
146+
value = this.transformValue(value, param);
147+
value = await this.validateValue(value, param);
143148
}
144149

145150
return value;

src/decorator/QueryParams.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export function QueryParams(options?: ParamOptions): Function {
1212
object: object,
1313
method: methodName,
1414
index: index,
15+
name: "",
1516
parse: options ? options.parse : false,
1617
required: options ? options.required : undefined,
1718
classTransform: options ? options.transform : undefined,

test/functional/action-params.spec.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import "reflect-metadata";
22

3-
import {IsString, IsBoolean, Min, MaxLength} from "class-validator";
3+
import {IsString, IsBoolean, Min, MaxLength, ValidateNested} from "class-validator";
44
import {getMetadataArgsStorage, createExpressServer, createKoaServer} from "../../src/index";
55
import {assertRequest} from "./test-utils";
66
import {User} from "../fakes/global-options/User";
@@ -85,6 +85,17 @@ describe("action parameters", () => {
8585
const {SetStateMiddleware} = require("../fakes/global-options/koa-middlewares/SetStateMiddleware");
8686
const {SessionMiddleware} = require("../fakes/global-options/SessionMiddleware");
8787

88+
class NestedQueryClass {
89+
@Min(5)
90+
num: number;
91+
92+
@IsString()
93+
str: string;
94+
95+
@IsBoolean()
96+
isFive: boolean;
97+
}
98+
8899
class QueryClass {
89100
@MaxLength(5)
90101
sortBy?: string;
@@ -97,6 +108,9 @@ describe("action parameters", () => {
97108

98109
@IsBoolean()
99110
showAll: boolean = true;
111+
112+
@ValidateNested()
113+
myObject: NestedQueryClass;
100114
}
101115

102116
@Controller()
@@ -498,7 +512,7 @@ describe("action parameters", () => {
498512
});
499513

500514
// todo: enable koa test when #227 fixed
501-
describe("@QueryParams should give a proper values from request query parameters", () => {
515+
describe("@QueryParams should give a proper values from request's query parameters", () => {
502516
assertRequest([3001, /*3002*/], "get", "photos-params?sortBy=name&count=2&limit=10&showAll", response => {
503517
expect(response).to.be.status(200);
504518
expect(response).to.have.header("content-type", "text/html; charset=utf-8");
@@ -509,6 +523,20 @@ describe("action parameters", () => {
509523
});
510524
});
511525

526+
describe("@QueryParams should give a proper values from request's query parameters with nested json", () => {
527+
assertRequest([3001, /*3002*/], "get", "photos-params?sortBy=name&count=2&limit=10&showAll&myObject=%7B%22num%22%3A%205,%20%22str%22%3A%20%22five%22,%20%22isFive%22%3A%20true%7D", response => {
528+
expect(response).to.be.status(200);
529+
expect(response).to.have.header("content-type", "text/html; charset=utf-8");
530+
expect(queryParams1.sortBy).to.be.equal("name");
531+
expect(queryParams1.count).to.be.equal("2");
532+
expect(queryParams1.limit).to.be.equal(10);
533+
expect(queryParams1.showAll).to.be.equal(true);
534+
expect(queryParams1.myObject.num).to.be.equal(5);
535+
expect(queryParams1.myObject.str).to.be.equal("five");
536+
expect(queryParams1.myObject.isFive).to.be.equal(true);
537+
});
538+
});
539+
512540
describe("@QueryParams should not validate request query parameters when it's turned off in validator options", () => {
513541
assertRequest([3001, 3002], "get", "photos-params-no-validate?sortBy=verylongtext&count=2&limit=1&showAll=true", response => {
514542
expect(response).to.be.status(200);
@@ -521,7 +549,7 @@ describe("action parameters", () => {
521549
});
522550

523551
// todo: enable koa test when #227 fixed
524-
describe("@QueryParams should give a proper values from request query parameters", () => {
552+
describe("@QueryParams should give a proper values from request's optional query parameters", () => {
525553
assertRequest([3001, /*3002*/], "get", "photos-params-optional?sortBy=name&limit=10", response => {
526554
expect(queryParams3.sortBy).to.be.equal("name");
527555
expect(queryParams3.count).to.be.equal(undefined);

0 commit comments

Comments
 (0)