springdoc / springdoc-openapi

Library for OpenAPI 3 with spring-boot

Home Page:https://springdoc.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mismatch between `org.springframework.data.domain.Page<ItemDto>` and the openapi spec

aconrad opened this issue · comments

Describe the bug

When my controller returns Page<...>, the JSON response has the keys content (containing the paged items) and page (containing the pageable info) but the openapi spec shows a different schema with keys such as content (as expected) but also pageable, totalElements, totalPages, first, last, etc... (see full list below). This started happening when I upgraded org.springframework.boot from 3.2.6 to 3.3.0.

Why doesn't the openapi spec reflect the returned data?

To Reproduce
Steps to reproduce the behavior:

  • What version of spring-boot you are using?
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.0</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
  • What modules and versions of springdoc-openapi are you using?
		<dependency>
			<groupId>org.springdoc</groupId>
			<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
			<version>2.5.0</version>
		</dependency>
  • What is the actual and the expected result using OpenAPI Description (yml or json)?

The openapi output (JSON, only the relevant part):

      "PageItemDto": {
        "type": "object",
        "properties": {
          "totalElements": {
            "type": "integer",
            "format": "int64"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "first": {
            "type": "boolean"
          },
          "last": {
            "type": "boolean"
          },
          "size": {
            "type": "integer",
            "format": "int32"
          },
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemDto"
            }
          },
          "number": {
            "type": "integer",
            "format": "int32"
          },
          "sort": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SortObject"
            }
          },
          "numberOfElements": {
            "type": "integer",
            "format": "int32"
          },
          "pageable": {
            "$ref": "#/components/schemas/PageableObject"
          },
          "empty": {
            "type": "boolean"
          }
        }
      },
  • Provide with a sample code (HelloController) or Test that reproduces the problem
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;

    @GetMapping("/my-endpoint")
    public Page<ItemDto> getItems(
                @ParameterObject @PageableDefault(page = 0, size = 10) Pageable pageable) {

        // ...

        return new PageImpl<>(items, pageable, dbObjects.getTotalElements());
    }

The data returned by the controller:

{
    "content": [
        {
            // serialized ItemDto
        },
        // ...
    ],
    "page": {
        "size": 10,
        "number": 0,
        "totalElements": 48,
        "totalPages": 5
    }
}

Expected behavior

  • A clear and concise description of what you expected to happen.

I expect the JSON output to describe PageItemDto with only 2 keys, content and page.

  • What is the expected result using OpenAPI Description (yml or json)?

Something like this (handcrafted, sorry if typos):

      "PageItemDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/Page"
          }
        }
      },
      "Page": {
        "type": "object",
        "properties": {
          "totalElements": {
            "type": "integer",
            "format": "int64"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "size": {
            "type": "integer",
            "format": "int32"
          },
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemDto"
            }
          },
          "number": {
            "type": "integer",
            "format": "int32"
          },
      },

Screenshots
If applicable, add screenshots to help explain your problem.

org.springframework.boot 3.3.0:

Screenshot 2024-06-18 at 6 56 28 PM

org.springframework.boot 3.2.6:

Screenshot 2024-06-18 at 6 58 18 PM

Additional context
Add any other context about the problem here.