Skip to content

Commit 26d58f2

Browse files
author
bnasslahsen
committed
Improve support of @parameter Schema, in case of @RequestBody. Fixes #396
1 parent f31f02b commit 26d58f2

File tree

7 files changed

+232
-29
lines changed

7 files changed

+232
-29
lines changed

Diff for: springdoc-openapi-common/src/main/java/org/springdoc/core/AbstractParameterBuilder.java

+21-16
Original file line numberDiff line numberDiff line change
@@ -185,35 +185,40 @@ else if (AnnotationsUtils.hasArrayAnnotation(parameterDoc.content()[0].array()))
185185
}
186186
}
187187

188-
Schema calculateSchema(Components components, java.lang.reflect.Parameter parameter, String paramName,
188+
Schema calculateSchema(Components components, ParameterInfo parameterInfo,
189189
RequestBodyInfo requestBodyInfo, JsonView jsonView) {
190190
Schema schemaN;
191191
Class<?> schemaImplementation = null;
192192
Type returnType = null;
193193
JavaType ct = null;
194-
194+
String paramName = parameterInfo.getpName();
195+
java.lang.reflect.Parameter parameter = parameterInfo.getParameter();
195196
if (parameter != null) {
196197
returnType = parameter.getParameterizedType();
197198
ct = constructType(parameter.getType());
198199
schemaImplementation = parameter.getType();
199200
}
200201

201-
if (isFile(ct)) {
202-
schemaN = getFileSchema(requestBodyInfo);
203-
schemaN.addProperties(paramName, new FileSchema());
204-
return schemaN;
205-
}
206-
207-
if (returnType instanceof ParameterizedType) {
208-
ParameterizedType parameterizedType = (ParameterizedType) returnType;
209-
if (isFile(parameterizedType)) {
210-
return extractFileSchema(paramName, requestBodyInfo);
202+
if (parameterInfo.getParameterModel() == null || parameterInfo.getParameterModel().getSchema() == null) {
203+
if (isFile(ct)) {
204+
schemaN = getFileSchema(requestBodyInfo);
205+
schemaN.addProperties(paramName, new FileSchema());
206+
return schemaN;
207+
} else if (returnType instanceof ParameterizedType) {
208+
ParameterizedType parameterizedType = (ParameterizedType) returnType;
209+
if (isFile(parameterizedType)) {
210+
return extractFileSchema(paramName, requestBodyInfo);
211+
}
212+
schemaN = calculateSchemaFromParameterizedType(components, returnType, jsonView);
213+
}
214+
else {
215+
schemaN = SpringDocAnnotationsUtils.resolveSchemaFromType(schemaImplementation, components, jsonView);
211216
}
212-
schemaN = calculateSchemaFromParameterizedType(components, returnType, jsonView);
213217
}
214218
else {
215-
schemaN = SpringDocAnnotationsUtils.resolveSchemaFromType(schemaImplementation, components, jsonView);
219+
schemaN = parameterInfo.getParameterModel().getSchema();
216220
}
221+
217222
if (requestBodyInfo != null) {
218223
if (requestBodyInfo.getMergedSchema() != null) {
219224
requestBodyInfo.getMergedSchema().addProperties(paramName, schemaN);
@@ -234,8 +239,8 @@ public LocalVariableTableParameterNameDiscoverer getLocalSpringDocParameterNameD
234239

235240
private Schema extractFileSchema(String paramName, RequestBodyInfo requestBodyInfo) {
236241
Schema schemaN = getFileSchema(requestBodyInfo);
237-
ArraySchema schemafile = new ArraySchema();
238-
schemafile.items(new FileSchema());
242+
ArraySchema schemaFile = new ArraySchema();
243+
schemaFile.items(new FileSchema());
239244
schemaN.addProperties(paramName, new ArraySchema().items(new FileSchema()));
240245
return schemaN;
241246
}

Diff for: springdoc-openapi-common/src/main/java/org/springdoc/core/AbstractRequestBuilder.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ public Operation build(Components components, HandlerMethod handlerMethod, Reque
178178
applyBeanValidatorAnnotations(parameter, Arrays.asList(parameters[i].getAnnotations()));
179179
}
180180
else if (!RequestMethod.GET.equals(requestMethod)) {
181-
requestBodyInfo.setRequestBody(operation.getRequestBody());
181+
if (operation.getRequestBody() != null)
182+
requestBodyInfo.setRequestBody(operation.getRequestBody());
182183
requestBodyBuilder.calculateRequestBodyInfo(components, handlerMethod, methodAttributes, i,
183184
parameterInfo, requestBodyInfo);
184185
}
@@ -328,7 +329,7 @@ private Parameter buildParam(String in, Components components, ParameterInfo par
328329
}
329330

330331
if (parameter.getSchema() == null) {
331-
Schema<?> schema = parameterBuilder.calculateSchema(components, parameterInfo.getParameter(), name, null,
332+
Schema<?> schema = parameterBuilder.calculateSchema(components, parameterInfo, null,
332333
jsonView);
333334
if (defaultValue != null)
334335
schema.setDefault(defaultValue);
@@ -442,7 +443,7 @@ private Map<String, io.swagger.v3.oas.annotations.Parameter> getApiParameters(Me
442443
return apiParametersMap;
443444
}
444445

445-
public static void addResponseWrapperToIgnore(Class<?>... classes){
446+
public static void addResponseWrapperToIgnore(Class<?>... classes) {
446447
PARAM_TYPES_TO_IGNORE.addAll(Arrays.asList(classes));
447448
}
448449
}

Diff for: springdoc-openapi-common/src/main/java/org/springdoc/core/RequestBodyBuilder.java

+3-10
Original file line numberDiff line numberDiff line change
@@ -120,23 +120,16 @@ private RequestBody buildRequestBody(RequestBody requestBody, Components compone
120120
io.swagger.v3.oas.models.parameters.Parameter parameter = parameterInfo.getParameterModel();
121121
if (StringUtils.isNotBlank(parameter.getDescription()))
122122
requestBody.setDescription(parameter.getDescription());
123-
if (parameter.getSchema() != null) {
124-
Schema<?> schema = parameterInfo.getParameterModel().getSchema();
125-
buildContent(requestBody, methodAttributes, schema);
126-
}
127123
requestBody.setRequired(parameter.getRequired());
128124
}
129125

130126
if (requestBody.getContent() == null) {
131-
Schema<?> schema = parameterBuilder.calculateSchema(components, parameterInfo.getParameter(),
132-
parameterInfo.getpName(), requestBodyInfo,
127+
Schema<?> schema = parameterBuilder.calculateSchema(components, parameterInfo, requestBodyInfo,
133128
methodAttributes.getJsonViewAnnotationForRequestBody());
134129
buildContent(requestBody, methodAttributes, schema);
135130
}
136-
else if (requestBody.getContent() != null && (methodAttributes.isMethodOverloaded() ||
137-
requestBody.getContent().values().stream().anyMatch(mediaType -> mediaType.getSchema() == null))) {
138-
Schema<?> schema = parameterBuilder.calculateSchema(components, parameterInfo.getParameter(),
139-
parameterInfo.getpName(), requestBodyInfo,
131+
else if (requestBodyInfo.getRequestBody()!=null) {
132+
Schema<?> schema = parameterBuilder.calculateSchema(components, parameterInfo, requestBodyInfo,
140133
methodAttributes.getJsonViewAnnotationForRequestBody());
141134
mergeContent(requestBody, methodAttributes, schema);
142135
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
*
3+
* * Copyright 2019-2020 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package test.org.springdoc.api.app83;
20+
21+
import io.swagger.v3.oas.annotations.Parameter;
22+
import io.swagger.v3.oas.annotations.media.Schema;
23+
24+
import org.springframework.http.MediaType;
25+
import org.springframework.http.ResponseEntity;
26+
import org.springframework.web.bind.annotation.PathVariable;
27+
import org.springframework.web.bind.annotation.RequestMapping;
28+
import org.springframework.web.bind.annotation.RequestMethod;
29+
import org.springframework.web.bind.annotation.RequestPart;
30+
import org.springframework.web.bind.annotation.RestController;
31+
import org.springframework.web.multipart.MultipartFile;
32+
33+
@RestController
34+
public class HelloController {
35+
36+
37+
@RequestMapping(value = "/{config}",
38+
method = RequestMethod.PUT,
39+
consumes = { MediaType.MULTIPART_FORM_DATA_VALUE},
40+
produces = {MediaType.APPLICATION_JSON_VALUE}
41+
)
42+
public ResponseEntity<?> put(
43+
@PathVariable("config") final String config,
44+
@Parameter(name = "configuration", schema = @Schema(name ="configuration", type = "string", format = "binary")) @RequestPart(value = "configuration") final PersonDTO configuration,
45+
@RequestPart(value = "file") final MultipartFile aFile) {
46+
return null;
47+
}
48+
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
*
3+
* * Copyright 2019-2020 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package test.org.springdoc.api.app83;
20+
21+
public class PersonDTO {
22+
private String email;
23+
24+
private String firstName;
25+
26+
private String lastName;
27+
28+
public PersonDTO() {
29+
}
30+
31+
public PersonDTO(final String email, final String firstName, final String lastName) {
32+
this.email = email;
33+
this.firstName = firstName;
34+
this.lastName = lastName;
35+
}
36+
37+
public String getEmail() {
38+
return email;
39+
}
40+
41+
public void setEmail(final String email) {
42+
this.email = email;
43+
}
44+
45+
public String getFirstName() {
46+
return firstName;
47+
}
48+
49+
public void setFirstName(final String firstName) {
50+
this.firstName = firstName;
51+
}
52+
53+
public String getLastName() {
54+
return lastName;
55+
}
56+
57+
public void setLastName(final String lastName) {
58+
this.lastName = lastName;
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
*
3+
* * Copyright 2019-2020 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package test.org.springdoc.api.app83;
20+
21+
import test.org.springdoc.api.AbstractSpringDocTest;
22+
23+
import org.springframework.boot.autoconfigure.SpringBootApplication;
24+
25+
public class SpringDocApp83Test extends AbstractSpringDocTest {
26+
27+
@SpringBootApplication
28+
static class SpringDocTestApp {}
29+
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"openapi": "3.0.1",
3+
"info": {
4+
"title": "OpenAPI definition",
5+
"version": "v0"
6+
},
7+
"servers": [
8+
{
9+
"url": "http://localhost",
10+
"description": "Generated server url"
11+
}
12+
],
13+
"paths": {
14+
"/{config}": {
15+
"put": {
16+
"tags": [
17+
"hello-controller"
18+
],
19+
"operationId": "put",
20+
"parameters": [
21+
{
22+
"name": "config",
23+
"in": "path",
24+
"required": true,
25+
"schema": {
26+
"type": "string"
27+
}
28+
}
29+
],
30+
"requestBody": {
31+
"content": {
32+
"multipart/form-data": {
33+
"schema": {
34+
"type": "object",
35+
"properties": {
36+
"configuration": {
37+
"type": "string",
38+
"format": "binary"
39+
},
40+
"file": {
41+
"type": "string",
42+
"format": "binary"
43+
}
44+
}
45+
}
46+
}
47+
}
48+
},
49+
"responses": {
50+
"200": {
51+
"description": "default response",
52+
"content": {
53+
"application/json": {
54+
"schema": {
55+
"type": "object"
56+
}
57+
}
58+
}
59+
}
60+
}
61+
}
62+
}
63+
},
64+
"components": {}
65+
}

0 commit comments

Comments
 (0)