Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public class MethodAttributes {
/**
* The Use return type schema.
*/
private boolean useReturnTypeSchema;
private final Map<String, Boolean> useReturnTypeSchema = new LinkedHashMap<>();

/**
* Instantiates a new Method attributes.
Expand Down Expand Up @@ -529,20 +529,21 @@ public Locale getLocale() {
}

/**
* Is use return type schema boolean.
* Gets use return type schema.
*
* @return the boolean
* @return the use return type schema
*/
public boolean isUseReturnTypeSchema() {
public Map<String, Boolean> getUseReturnTypeSchema() {
return useReturnTypeSchema;
}

/**
* Sets use return type schema.
* Put use return type schema.
*
* @param responseCode the response code
* @param useReturnTypeSchema the use return type schema
*/
public void setUseReturnTypeSchema(boolean useReturnTypeSchema) {
this.useReturnTypeSchema = useReturnTypeSchema;
public void putUseReturnTypeSchema(String responseCode, boolean useReturnTypeSchema) {
this.useReturnTypeSchema.put(responseCode, useReturnTypeSchema);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,22 +180,22 @@ public GenericResponseService(OperationService operationService,
* @param components the components
* @param apiResponsesOp the api responses op
* @param methodAttributes the method attributes
* @param apiResponseAnnotations the api response annotations
* @param apiResponseAnnotation the api response annotation
* @param apiResponse the api response
* @param openapi31 the openapi 31
*/
public static void buildContentFromDoc(Components components, ApiResponses apiResponsesOp,
MethodAttributes methodAttributes,
io.swagger.v3.oas.annotations.responses.ApiResponse apiResponseAnnotations,
io.swagger.v3.oas.annotations.responses.ApiResponse apiResponseAnnotation,
ApiResponse apiResponse, boolean openapi31) {

methodAttributes.setUseReturnTypeSchema(apiResponseAnnotations.useReturnTypeSchema());
io.swagger.v3.oas.annotations.media.Content[] contentdoc = apiResponseAnnotations.content();
methodAttributes.putUseReturnTypeSchema(apiResponseAnnotation.responseCode(), apiResponseAnnotation.useReturnTypeSchema());
io.swagger.v3.oas.annotations.media.Content[] contentdoc = apiResponseAnnotation.content();
Optional<Content> optionalContent = getContent(contentdoc, new String[0],
methodAttributes.getMethodProduces(), null, components, methodAttributes.getJsonViewAnnotation(), openapi31);
if (apiResponsesOp.containsKey(apiResponseAnnotations.responseCode())) {
if (apiResponsesOp.containsKey(apiResponseAnnotation.responseCode())) {
// Merge with the existing content
Content existingContent = apiResponsesOp.get(apiResponseAnnotations.responseCode()).getContent();
Content existingContent = apiResponsesOp.get(apiResponseAnnotation.responseCode()).getContent();
if (optionalContent.isPresent()) {
Content newContent = optionalContent.get();
if (methodAttributes.isMethodOverloaded() && existingContent != null) {
Expand Down Expand Up @@ -387,17 +387,17 @@ private Map<String, ApiResponse> computeResponseFromDoc(Components components, M
Set<io.swagger.v3.oas.annotations.responses.ApiResponse> responsesArray = getApiResponses(Objects.requireNonNull(methodParameter.getMethod()));
if (!responsesArray.isEmpty()) {
methodAttributes.setWithApiResponseDoc(true);
for (io.swagger.v3.oas.annotations.responses.ApiResponse apiResponseAnnotations : responsesArray) {
String httpCode = apiResponseAnnotations.responseCode();
for (io.swagger.v3.oas.annotations.responses.ApiResponse apiResponseAnnotation : responsesArray) {
String httpCode = apiResponseAnnotation.responseCode();
ApiResponse apiResponse = new ApiResponse();
if (StringUtils.isNotBlank(apiResponseAnnotations.ref())) {
apiResponse.$ref(apiResponseAnnotations.ref());
apiResponsesOp.addApiResponse(apiResponseAnnotations.responseCode(), apiResponse);
if (StringUtils.isNotBlank(apiResponseAnnotation.ref())) {
apiResponse.$ref(apiResponseAnnotation.ref());
apiResponsesOp.addApiResponse(apiResponseAnnotation.responseCode(), apiResponse);
continue;
}
apiResponse.setDescription(propertyResolverUtils.resolve(apiResponseAnnotations.description(), methodAttributes.getLocale()));
buildContentFromDoc(components, apiResponsesOp, methodAttributes, apiResponseAnnotations, apiResponse, openapi31);
Map<String, Object> extensions = AnnotationsUtils.getExtensions(propertyResolverUtils.isOpenapi31(), apiResponseAnnotations.extensions());
apiResponse.setDescription(propertyResolverUtils.resolve(apiResponseAnnotation.description(), methodAttributes.getLocale()));
buildContentFromDoc(components, apiResponsesOp, methodAttributes, apiResponseAnnotation, apiResponse, openapi31);
Map<String, Object> extensions = AnnotationsUtils.getExtensions(propertyResolverUtils.isOpenapi31(), apiResponseAnnotation.extensions());
if (!CollectionUtils.isEmpty(extensions)) {
if (propertyResolverUtils.isResolveExtensionsProperties()) {
Map<String, Object> extensionsResolved = propertyResolverUtils.resolveExtensions(locale, extensions);
Expand All @@ -407,7 +407,7 @@ private Map<String, ApiResponse> computeResponseFromDoc(Components components, M
apiResponse.extensions(extensions);
}
}
SpringDocAnnotationsUtils.getHeaders(apiResponseAnnotations.headers(), components, methodAttributes.getJsonViewAnnotation(), openapi31)
SpringDocAnnotationsUtils.getHeaders(apiResponseAnnotation.headers(), components, methodAttributes.getJsonViewAnnotation(), openapi31)
.ifPresent(apiResponse::headers);
apiResponsesOp.addApiResponse(httpCode, apiResponse);
}
Expand Down Expand Up @@ -622,8 +622,7 @@ else if (CollectionUtils.isEmpty(apiResponse.getContent()))
setDescription(httpCode, apiResponse);
}
}
if (apiResponse.getContent() != null && (methodAttributes.isUseReturnTypeSchema() ||
((isGeneric || methodAttributes.isMethodOverloaded()) && methodAttributes.isNoApiResponseDoc()))) {
if (apiResponse.getContent() != null && shouldCalculateContent(methodAttributes, isGeneric, httpCode)) {
// Merge with existing schema
Content existingContent = apiResponse.getContent();
Type type = GenericTypeResolver.resolveType(methodParameter.getGenericParameterType(), methodParameter.getContainingClass());
Expand All @@ -642,6 +641,28 @@ else if (CollectionUtils.isEmpty(apiResponse.getContent()))
apiResponsesOp.addApiResponse(httpCode, apiResponse);
}

/**
* Whether to consider calculating additional content.
*
* @param methodAttributes the method attributes
* @param isGeneric the is generic
* @param httpCode the http code
*/
private boolean shouldCalculateContent(MethodAttributes methodAttributes, boolean isGeneric, String httpCode) {
return useReturnTypeSchema(methodAttributes, httpCode) ||
((isGeneric || methodAttributes.isMethodOverloaded()) && methodAttributes.isNoApiResponseDoc());
}

/**
* Whether to use return type schema.
*
* @param methodAttributes the method attributes
* @param httpCode the http code
*/
private boolean useReturnTypeSchema(MethodAttributes methodAttributes, String httpCode) {
return methodAttributes.getUseReturnTypeSchema().getOrDefault(httpCode, false);
}

/**
* Evaluate response status string.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;

import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -17,20 +19,35 @@
@RequestMapping
public class HelloController {

public record Error(String message) {

}

@PostMapping("/testBoolean")
@ApiResponse(
useReturnTypeSchema = true,
responseCode = "200",
description = "OK",
content = {
@Content(
mediaType = "*/*",
examples =
@ExampleObject(
name = "success",
value = "..."))
}
)
@ApiResponses(value = {
@ApiResponse(
useReturnTypeSchema = true,
responseCode = "200",
description = "OK",
content = {
@Content(
mediaType = "*/*",
examples =
@ExampleObject(
name = "success",
value = "..."))
}
),
@ApiResponse(
responseCode = "400",
description = "OK",
content = {
@Content(
mediaType = "*/*",
schema = @Schema(implementation = Error.class))
}
)
})
public Map<String, String> HelloController() {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;

import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -17,20 +19,35 @@
@RequestMapping
public class HelloController {

public record Error(String message) {

}

@PostMapping("/testBoolean")
@ApiResponse(
useReturnTypeSchema = true,
responseCode = "200",
description = "OK",
content = {
@Content(
mediaType = "*/*",
examples =
@ExampleObject(
name = "success",
value = "..."))
}
)
@ApiResponses(value = {
@ApiResponse(
useReturnTypeSchema = true,
responseCode = "200",
description = "OK",
content = {
@Content(
mediaType = "*/*",
examples =
@ExampleObject(
name = "success",
value = "..."))
}
),
@ApiResponse(
responseCode = "400",
description = "OK",
content = {
@Content(
mediaType = "*/*",
schema = @Schema(implementation = Error.class))
}
)
})
public Map<String, String> HelloController() {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,31 @@
}
}
}
},
"400" : {
"description" : "OK",
"content" : {
"*/*" : {
"schema" : {
"$ref" : "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {}
"components": {
"schemas" : {
"Error" : {
"type" : "object",
"properties" : {
"message" : {
"type" : "string"
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,45 +1,62 @@
{
"openapi": "3.1.0",
"info": {
"title": "OpenAPI definition",
"version": "v0"
"openapi" : "3.1.0",
"info" : {
"title" : "OpenAPI definition",
"version" : "v0"
},
"servers": [
{
"url": "http://localhost",
"description": "Generated server url"
}
],
"paths": {
"/testBoolean": {
"post": {
"tags": [
"hello-controller"
],
"operationId": "HelloController",
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
"servers" : [ {
"url" : "http://localhost",
"description" : "Generated server url"
} ],
"paths" : {
"/testBoolean" : {
"post" : {
"tags" : [ "hello-controller" ],
"operationId" : "HelloController",
"responses" : {
"200" : {
"description" : "OK",
"content" : {
"*/*" : {
"schema" : {
"type" : "object",
"additionalProperties" : {
"type" : "string"
}
},
"examples": {
"success": {
"description": "success",
"value": "..."
"examples" : {
"success" : {
"description" : "success",
"value" : "..."
}
}
}
}
},
"400" : {
"description" : "OK",
"content" : {
"*/*" : {
"schema" : {
"$ref" : "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {}
}
"components" : {
"schemas" : {
"Error" : {
"type" : "object",
"properties" : {
"message" : {
"type" : "string"
}
}
}
}
}
}