Skip to content

Commit 7ad1bb7

Browse files
committed
Query parameter part of request body in controller with MultiPartFile. Fixes springdoc#1793
1 parent 3e8e84e commit 7ad1bb7

File tree

7 files changed

+269
-2
lines changed

7 files changed

+269
-2
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/core/AbstractRequestService.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ public abstract class AbstractRequestService {
171171
*/
172172
private final boolean defaultFlatParamObject;
173173

174+
/**
175+
* The Default support form data.
176+
*/
177+
private boolean defaultSupportFormData;
178+
179+
174180
/**
175181
* Instantiates a new Abstract request builder.
176182
*
@@ -191,6 +197,8 @@ protected AbstractRequestService(GenericParameterService parameterBuilder, Reque
191197
this.parameterCustomizers = parameterCustomizers;
192198
this.localSpringDocParameterNameDiscoverer = localSpringDocParameterNameDiscoverer;
193199
this.defaultFlatParamObject = parameterBuilder.getPropertyResolverUtils().getSpringDocConfigProperties().isDefaultFlatParamObject();
200+
this.defaultSupportFormData = parameterBuilder.getPropertyResolverUtils().getSpringDocConfigProperties().isDefaultSupportFormData();
201+
194202
}
195203

196204
/**
@@ -319,7 +327,7 @@ else if (!RequestMethod.GET.equals(requestMethod)) {
319327
LinkedHashMap<String, Parameter> map = getParameterLinkedHashMap(components, methodAttributes, operationParameters, parametersDocMap);
320328
RequestBody requestBody = requestBodyInfo.getRequestBody();
321329
// support form-data
322-
if (requestBody != null
330+
if (defaultSupportFormData && requestBody != null
323331
&& requestBody.getContent() != null
324332
&& requestBody.getContent().containsKey(org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE)) {
325333
io.swagger.v3.oas.models.media.Schema<?> mergedSchema = requestBodyInfo.getMergedSchema();

springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocConfigProperties.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ public class SpringDocConfigProperties {
181181
*/
182182
private boolean defaultFlatParamObject;
183183

184+
/**
185+
* convert query param to form data when consumes is multipart/form-data
186+
*/
187+
private boolean defaultSupportFormData=true;
188+
184189
/**
185190
* The model Converters
186191
*/
@@ -191,6 +196,24 @@ public class SpringDocConfigProperties {
191196
*/
192197
private SortConverter sortConverter = new SortConverter();
193198

199+
/**
200+
* Is default support form data boolean.
201+
*
202+
* @return the boolean
203+
*/
204+
public boolean isDefaultSupportFormData() {
205+
return defaultSupportFormData;
206+
}
207+
208+
/**
209+
* Sets default support form data.
210+
*
211+
* @param defaultSupportFormData the default support form data
212+
*/
213+
public void setDefaultSupportFormData(boolean defaultSupportFormData) {
214+
this.defaultSupportFormData = defaultSupportFormData;
215+
}
216+
194217
/**
195218
* Gets sort converter.
196219
*
@@ -821,7 +844,7 @@ public void setPolymorphicConverter(PolymorphicConverter polymorphicConverter) {
821844

822845
/**
823846
* The type Sort converter.
824-
* @author daniel-shuy
847+
* @author daniel -shuy
825848
*/
826849
public static class SortConverter {
827850

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package test.org.springdoc.api.v30.app194;
2+
3+
import java.util.LinkedList;
4+
import java.util.List;
5+
6+
import io.swagger.v3.oas.annotations.tags.Tag;
7+
import org.springdoc.api.annotations.ParameterObject;
8+
9+
import org.springframework.http.MediaType;
10+
import org.springframework.web.bind.annotation.GetMapping;
11+
import org.springframework.web.bind.annotation.PostMapping;
12+
import org.springframework.web.bind.annotation.RequestPart;
13+
import org.springframework.web.bind.annotation.RestController;
14+
import org.springframework.web.multipart.MultipartFile;
15+
16+
@Tag(name = "Article Api")
17+
@RestController("/article")
18+
public class ArticleApi {
19+
20+
@GetMapping("query")
21+
public List<ArticleDto> query(@ParameterObject ArticleQueryCondition condition) {
22+
return new LinkedList<>();
23+
}
24+
25+
@PostMapping(value = "create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
26+
public ArticleDto create(@ParameterObject ArticleDto dto, @RequestPart MultipartFile file) {
27+
return new ArticleDto();
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package test.org.springdoc.api.v30.app194;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
5+
@Schema
6+
public class ArticleDto {
7+
@Schema(description = "title")
8+
private String title;
9+
10+
@Schema(description = "content")
11+
private String content;
12+
13+
public String getTitle() {
14+
return title;
15+
}
16+
17+
public void setTitle(String title) {
18+
this.title = title;
19+
}
20+
21+
public String getContent() {
22+
return content;
23+
}
24+
25+
public void setContent(String content) {
26+
this.content = content;
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package test.org.springdoc.api.v30.app194;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
@Schema
5+
public class ArticleQueryCondition {
6+
@Schema(description = "title")
7+
private String title;
8+
9+
public String getTitle() {
10+
return title;
11+
}
12+
13+
public void setTitle(String title) {
14+
this.title = title;
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2022 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*/
22+
23+
package test.org.springdoc.api.v30.app194;
24+
25+
import test.org.springdoc.api.v30.AbstractSpringDocV30Test;
26+
27+
import org.springframework.boot.autoconfigure.SpringBootApplication;
28+
import org.springframework.test.context.TestPropertySource;
29+
30+
@TestPropertySource(properties = "springdoc.default-support-form-data=false")
31+
public class SpringDocApp194Test extends AbstractSpringDocV30Test {
32+
33+
@SpringBootApplication
34+
static class SpringDocTestApp {}
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
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+
"/create": {
15+
"post": {
16+
"tags": [
17+
"Article Api"
18+
],
19+
"operationId": "create",
20+
"parameters": [
21+
{
22+
"name": "title",
23+
"in": "query",
24+
"description": "title",
25+
"required": false,
26+
"schema": {
27+
"type": "string",
28+
"description": "title"
29+
}
30+
},
31+
{
32+
"name": "content",
33+
"in": "query",
34+
"description": "content",
35+
"required": false,
36+
"schema": {
37+
"type": "string",
38+
"description": "content"
39+
}
40+
}
41+
],
42+
"requestBody": {
43+
"content": {
44+
"multipart/form-data": {
45+
"schema": {
46+
"required": [
47+
"file"
48+
],
49+
"type": "object",
50+
"properties": {
51+
"file": {
52+
"type": "string",
53+
"format": "binary"
54+
}
55+
}
56+
}
57+
}
58+
}
59+
},
60+
"responses": {
61+
"200": {
62+
"description": "OK",
63+
"content": {
64+
"*/*": {
65+
"schema": {
66+
"$ref": "#/components/schemas/ArticleDto"
67+
}
68+
}
69+
}
70+
}
71+
}
72+
}
73+
},
74+
"/query": {
75+
"get": {
76+
"tags": [
77+
"Article Api"
78+
],
79+
"operationId": "query",
80+
"parameters": [
81+
{
82+
"name": "title",
83+
"in": "query",
84+
"description": "title",
85+
"required": false,
86+
"schema": {
87+
"type": "string",
88+
"description": "title"
89+
}
90+
}
91+
],
92+
"responses": {
93+
"200": {
94+
"description": "OK",
95+
"content": {
96+
"*/*": {
97+
"schema": {
98+
"type": "array",
99+
"items": {
100+
"$ref": "#/components/schemas/ArticleDto"
101+
}
102+
}
103+
}
104+
}
105+
}
106+
}
107+
}
108+
}
109+
},
110+
"components": {
111+
"schemas": {
112+
"ArticleDto": {
113+
"type": "object",
114+
"properties": {
115+
"title": {
116+
"type": "string",
117+
"description": "title"
118+
},
119+
"content": {
120+
"type": "string",
121+
"description": "content"
122+
}
123+
}
124+
}
125+
}
126+
}
127+
}

0 commit comments

Comments
 (0)