diff --git a/src/middlewares/parsers/req.parameter.mutator.ts b/src/middlewares/parsers/req.parameter.mutator.ts index 907c3c4a..c4b3b8d3 100644 --- a/src/middlewares/parsers/req.parameter.mutator.ts +++ b/src/middlewares/parsers/req.parameter.mutator.ts @@ -103,12 +103,25 @@ export class RequestParameterMutator { }); } - private handleDeepObject(req: Request, qs: string, name: string, schema: SchemaObject): void { + private handleDeepObject( + req: Request, + qs: string, + name: string, + schema: SchemaObject, + ): void { const getDefaultSchemaValue = () => { let defaultValue; if (schema.default !== undefined) { - defaultValue = schema.default + defaultValue = schema.default; + } else if (schema.properties) { + Object.entries(schema.properties).forEach(([k, v]) => { + // Handle recursive objects + defaultValue ??= {}; + if (v['default']) { + defaultValue[k] = v['default']; + } + }); } else { ['allOf', 'oneOf', 'anyOf'].forEach((key) => { if (schema[key]) { @@ -116,9 +129,13 @@ export class RequestParameterMutator { if (s.$ref) { const compiledSchema = this.ajv.getSchema(s.$ref); // as any -> https://stackoverflow.com/a/23553128 - defaultValue = defaultValue === undefined ? (compiledSchema.schema as any).default : defaultValue; + defaultValue = + defaultValue === undefined + ? (compiledSchema.schema as any).default + : defaultValue; } else { - defaultValue = defaultValue === undefined ? s.default : defaultValue; + defaultValue = + defaultValue === undefined ? s.default : defaultValue; } }); } diff --git a/test/resources/serialized-deep-object.objects.yaml b/test/resources/serialized-deep-object.objects.yaml index 8da7a5e1..4ede419f 100644 --- a/test/resources/serialized-deep-object.objects.yaml +++ b/test/resources/serialized-deep-object.objects.yaml @@ -40,23 +40,47 @@ paths: responses: "200": description: the object + /deep_object_2: + get: + parameters: + - $ref: '#/components/parameters/pedestrian' + responses: + "200": + description: the object components: schemas: - Deep: + Pedestrian: type: object properties: - tag_ids: - type: array - items: - type: integer - minimum: 0 - minItems: 1 - state: - type: string - enum: ["default", "validated", "pending"] - default: "default" - description: "Filter the tags by their validity. The default value ('default') stands for no filtering." - greeting: - type: string - default: "hello" + speed: + type: number + format: double + minimum: 0.5 + maximum: 2 + default: 1 + # Deep: + # type: object + # properties: + # tag_ids: + # type: array + # items: + # type: integer + # minimum: 0 + # minItems: 1 + # state: + # type: string + # enum: ["default", "validated", "pending"] + # default: "default" + # description: "Filter the tags by their validity. The default value ('default') stands for no filtering." + # greeting: + # type: string + # default: "hello" + + parameters: + pedestrian: + name: pedestrian + in: query + style: deepObject + schema: + $ref: '#/components/schemas/Pedestrian' diff --git a/test/serialized-deep-object.objects.spec.ts b/test/serialized-deep-object.objects.spec.ts index 836fbc19..66d41920 100644 --- a/test/serialized-deep-object.objects.spec.ts +++ b/test/serialized-deep-object.objects.spec.ts @@ -10,13 +10,18 @@ describe(packageJson.name, () => { before(async () => { // Set up the express app - const apiSpec = path.join('test', 'resources', 'serialized-deep-object.objects.yaml'); + const apiSpec = path.join( + 'test', + 'resources', + 'serialized-deep-object.objects.yaml', + ); app = await createApp({ apiSpec }, 3005, (app) => app.use( `${app.basePath}`, express .Router() .get(`/deep_object`, (req, res) => res.json(req.query)) + .get(`/deep_object_2`, (req, res) => res.json(req.query)), ), ); }); @@ -25,6 +30,16 @@ describe(packageJson.name, () => { app.server.close(); }); + it('should explode deepObject and set default', async () => + request(app) + .get(`${app.basePath}/deep_object_2`) + .expect(200) + .then((r) => { + expect(r.body).to.deep.equals({ + pedestrian: { speed: 1 }, + }); + })); + it('should explode deepObject query params', async () => request(app) .get(`${app.basePath}/deep_object?settings[state]=default`) @@ -33,8 +48,8 @@ describe(packageJson.name, () => { const expected = { settings: { greeting: 'hello', - state: 'default' - } + state: 'default', + }, }; expect(r.body).to.deep.equals(expected); })); @@ -45,6 +60,11 @@ describe(packageJson.name, () => { .expect(200) .then((r) => { const expected = {}; - expect(r.body).to.deep.equals(expected); + expect(r.body).to.deep.equals({ + settings: { + greeting: 'hello', + state: 'default', + }, + }); })); });