Skip to content

Commit 7e45bea

Browse files
committed
Wrong schema generation with PagedModel generated VIA_DTO and wrapped in ResponseEntity. Fixes #2933
1 parent c32a017 commit 7e45bea

File tree

4 files changed

+138
-8
lines changed

4 files changed

+138
-8
lines changed

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PageOpenAPIConverter.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
package org.springdoc.core.converters;
2828

29-
import java.lang.reflect.ParameterizedType;
3029
import java.lang.reflect.Type;
3130
import java.util.Iterator;
3231

@@ -94,7 +93,7 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
9493
Class<?> cls = javaType.getRawClass();
9594
if (replacePageWithPagedModel && PAGE_TO_REPLACE.equals(cls.getCanonicalName())) {
9695
if (!type.isSchemaProperty())
97-
type = resolvePagedModelType(type);
96+
type = resolvePagedModelType(javaType);
9897
else
9998
type.name(getParentTypeName(type, cls));
10099
}
@@ -108,13 +107,12 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
108107
* @param type the type
109108
* @return the annotated type
110109
*/
111-
private AnnotatedType resolvePagedModelType(AnnotatedType type) {
112-
Type pageType = type.getType();
113-
if (pageType instanceof ParameterizedType) {
114-
Type argumentType = ((ParameterizedType) type.getType()).getActualTypeArguments()[0];
110+
private AnnotatedType resolvePagedModelType(JavaType type) {
111+
if(type.hasGenericTypes()){
112+
JavaType innerType = type.containedType(0);
115113
Type pagedModelType = ResolvableType
116-
.forClassWithGenerics(PagedModel.class, ResolvableType.forType(argumentType))
117-
.getType();
114+
.forClassWithGenerics(PagedModel.class, ResolvableType.forType(innerType))
115+
.getType();
118116
return new AnnotatedType(pagedModelType).resolveAsRef(true);
119117
}
120118
else {

springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v30/app10/HelloController.java

+10
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.data.domain.Page;
3232
import org.springframework.data.domain.PageImpl;
3333
import org.springframework.data.web.PagedModel;
34+
import org.springframework.http.ResponseEntity;
3435
import org.springframework.web.bind.annotation.GetMapping;
3536
import org.springframework.web.bind.annotation.RestController;
3637

@@ -43,6 +44,11 @@ public Page<String> pageSimple() {
4344
return pageImpl("test");
4445
}
4546

47+
@GetMapping("/page-simple-response")
48+
public ResponseEntity<Page<UserDto>> pageSimpleResponse() {
49+
return null;
50+
}
51+
4652
@GetMapping("/paged-model-simple")
4753
public PagedModel<String> pagedModelSimple() {
4854
return pagedModel("test");
@@ -76,4 +82,8 @@ private <T> Page<T> pageImpl(T value) {
7682
return new PageImpl<>(List.of(value));
7783
}
7884

85+
public record UserDto(
86+
String id,
87+
String email
88+
) {}
7989
}

springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/resources/results/3.0.1/app10-direct.json

+77
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,26 @@
9191
}
9292
}
9393
},
94+
"/page-simple-response": {
95+
"get": {
96+
"tags": [
97+
"hello-controller"
98+
],
99+
"operationId": "pageSimpleResponse",
100+
"responses": {
101+
"200": {
102+
"description": "OK",
103+
"content": {
104+
"*/*": {
105+
"schema": {
106+
"$ref": "#/components/schemas/PageUserDto"
107+
}
108+
}
109+
}
110+
}
111+
}
112+
}
113+
},
94114
"/page-raw": {
95115
"get": {
96116
"tags": [
@@ -294,6 +314,63 @@
294314
}
295315
}
296316
},
317+
"PageUserDto": {
318+
"type": "object",
319+
"properties": {
320+
"totalPages": {
321+
"type": "integer",
322+
"format": "int32"
323+
},
324+
"totalElements": {
325+
"type": "integer",
326+
"format": "int64"
327+
},
328+
"size": {
329+
"type": "integer",
330+
"format": "int32"
331+
},
332+
"content": {
333+
"type": "array",
334+
"items": {
335+
"$ref": "#/components/schemas/UserDto"
336+
}
337+
},
338+
"number": {
339+
"type": "integer",
340+
"format": "int32"
341+
},
342+
"sort": {
343+
"$ref": "#/components/schemas/SortObject"
344+
},
345+
"pageable": {
346+
"$ref": "#/components/schemas/PageableObject"
347+
},
348+
"first": {
349+
"type": "boolean"
350+
},
351+
"last": {
352+
"type": "boolean"
353+
},
354+
"numberOfElements": {
355+
"type": "integer",
356+
"format": "int32"
357+
},
358+
"empty": {
359+
"type": "boolean"
360+
}
361+
}
362+
},
363+
"UserDto": {
364+
"type": "object",
365+
"properties": {
366+
"id": {
367+
"type": "string"
368+
},
369+
"email": {
370+
"type": "string"
371+
}
372+
}
373+
},
297374
"Page": {
298375
"type": "object",
299376
"properties": {

springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/resources/results/3.0.1/app10-via_dto.json

+45
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,26 @@
9191
}
9292
}
9393
},
94+
"/page-simple-response": {
95+
"get": {
96+
"tags": [
97+
"hello-controller"
98+
],
99+
"operationId": "pageSimpleResponse",
100+
"responses": {
101+
"200": {
102+
"description": "OK",
103+
"content": {
104+
"*/*": {
105+
"schema": {
106+
"$ref": "#/components/schemas/PagedModelUserDto"
107+
}
108+
}
109+
}
110+
}
111+
}
112+
}
113+
},
94114
"/page-raw": {
95115
"get": {
96116
"tags": [
@@ -207,6 +227,31 @@
207227
"$ref": "#/components/schemas/PageMetadata"
208228
}
209229
}
230+
},
231+
"PagedModelUserDto": {
232+
"type": "object",
233+
"properties": {
234+
"content": {
235+
"type": "array",
236+
"items": {
237+
"$ref": "#/components/schemas/UserDto"
238+
}
239+
},
240+
"page": {
241+
"$ref": "#/components/schemas/PageMetadata"
242+
}
243+
}
244+
},
245+
"UserDto": {
246+
"type": "object",
247+
"properties": {
248+
"id": {
249+
"type": "string"
250+
},
251+
"email": {
252+
"type": "string"
253+
}
254+
}
210255
}
211256
}
212257
}

0 commit comments

Comments
 (0)