Skip to content

fix(response-object-factory): preserve example/examples for built-in scalar response types#3883

Merged
kamilmysliwiec merged 2 commits into
nestjs:masterfrom
yogeshwaran-c:fix/response-factory-builtin-type-example
Apr 30, 2026
Merged

fix(response-object-factory): preserve example/examples for built-in scalar response types#3883
kamilmysliwiec merged 2 commits into
nestjs:masterfrom
yogeshwaran-c:fix/response-factory-builtin-type-example

Conversation

@yogeshwaran-c

Copy link
Copy Markdown
Contributor

What kind of change does this PR introduce?

Bug fix.

What is the current behavior?

When a response decorator is configured with a built-in scalar (or array of scalar) type and an example payload, the example is silently dropped from the generated OpenAPI document.

@ApiOkResponse({ type: Number, example: 42 })
findAge() { ... }

The generated 200 response has no example:

{
  "description": "",
  "content": {
    "application/json": { "schema": { "type": "number" } }
  }
}

ResponseObjectFactory#create strips example and examples from the response via omit(response, exampleKeys) for the built-in-type branch, but it never re-attaches them to the generated media-type entry. The non-built-in (DTO) branch — handled by ResponseObjectMapper — already does the right thing via pick(response, exampleKeys) when it constructs the media type. The built-in-type branch is the outlier.

What is the new behavior?

example / examples are now forwarded to MimetypeContentWrapper.wrap for both the scalar and array-of-scalar built-in-type code paths, mirroring the DTO behaviour. The example ends up next to schema inside each content[<mimetype>] entry, as required by the OpenAPI spec, and is no longer left behind at the response top level.

{
  "description": "",
  "content": {
    "application/json": {
      "schema": { "type": "number" },
      "example": 42
    }
  }
}

Additional context (optional)

Added a focused unit test for ResponseObjectFactory covering scalar example, scalar examples, the isArray: true codepath, and a guard that example does not leak back to the top-level response object. The full swagger-explorer and response-object-mapper suites continue to pass (63 tests).

…scalar response types

When a response decorator is configured with a built-in scalar/array
type and an example payload, e.g.

    @ApiOkResponse({ type: Number, example: 42 })

ResponseObjectFactory#create stripped `example` and `examples` from
the response via `omit(response, exampleKeys)` but never re-attached
them to the generated media-type entry. As a result the example
silently disappeared from the OpenAPI document.

For non-built-in (DTO) types and array-of-DTO responses, the
ResponseObjectMapper already pipes `example`/`examples` into the
media-type wrapper via `pick(response, exampleKeys)`. Apply the same
treatment to the built-in-type branch so that scalar (and array of
scalar) responses keep their examples.
@kamilmysliwiec

Copy link
Copy Markdown
Member

Could you update e2e tests as well?

…calar responses

Adds three new cats-controller endpoints exercising the bug fixed in this
PR: a scalar @apiresponse with a single example, a scalar @apiresponse
with named examples, and an isArray scalar response with example. The
new validate-schema e2e check confirms each example/examples entry lands
inside content[application/json] and is not left behind at the response
top level.
@yogeshwaran-c

Copy link
Copy Markdown
Contributor Author

@kamilmysliwiec done — pushed 1f305df which adds e2e coverage for this fix.

Three new endpoints in `e2e/src/cats/cats.controller.ts`:

  • `GET /cats/scalar-with-example` — `@ApiResponse({ status: 200, type: Number, example: 42 })`
  • `GET /cats/scalar-with-examples` — `@ApiResponse({ ..., examples: { adult, kitten } })`
  • `GET /cats/array-of-scalar-with-example` — `@ApiResponse({ ..., type: String, isArray: true, example: ['Mau', 'Persian'] })`

A new test in `e2e/validate-schema.e2e-spec.ts` (`should preserve example/examples for built-in scalar response types`) asserts:

  • `example` lands at `responses['200'].content['application/json'].example` (not at the response top level)
  • `examples` keyed-object survives intact
  • The array path produces `schema: { type: 'array', items: { type: 'string' } }` with the example alongside

`npm run test:e2e -- validate-schema -t "preserve example"` → 2/2 passing on the new test plus the existing #3335 sibling.

@kamilmysliwiec kamilmysliwiec merged commit c3ebb0f into nestjs:master Apr 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants