diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/EnumDescription.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/EnumDescription.java new file mode 100644 index 000000000..aa4fef21e --- /dev/null +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/EnumDescription.java @@ -0,0 +1,51 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * + * * * * + * * * + * * + * + */ + +package org.springdoc.core.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Scans an Enum class from the annotated field and automatically adds its constants + * and descriptions to the OpenAPI documentation. + * + * @author TAEWOOKK + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface EnumDescription { + + /** + * The field name in the Enum class to read for description. + * If left empty (default), the library will attempt to find "description" field. + * + * @return The name of the field to read (e.g., "label", "description", "value"). + */ + String fieldName() default ""; +} diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocConfiguration.java index b29518f35..a80f7cc31 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocConfiguration.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocConfiguration.java @@ -75,6 +75,7 @@ import org.springdoc.core.customizers.RouterOperationCustomizer; import org.springdoc.core.customizers.ServerBaseUrlCustomizer; import org.springdoc.core.customizers.SpringDocCustomizers; +import org.springdoc.core.customizers.EnumDescriptionOperationCustomizer; import org.springdoc.core.discoverer.SpringDocParameterNameDiscoverer; import org.springdoc.core.events.SpringDocAppInitializer; import org.springdoc.core.extractor.MethodParameterPojoExtractor; @@ -719,6 +720,18 @@ MethodParameterPojoExtractor methodParameterPojoExtractor(SchemaUtils schemaUtil return new MethodParameterPojoExtractor(schemaUtils); } + /** + * Enum description operation customizer. + * + * @return the enum description operation customizer + */ + @Bean + @ConditionalOnMissingBean + @Lazy(false) + GlobalOperationCustomizer enumDescriptionOperationCustomizer() { + return new EnumDescriptionOperationCustomizer(); + } + /** * Spring doc app initializer spring doc app initializer. * diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/EnumDescriptionOperationCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/EnumDescriptionOperationCustomizer.java new file mode 100644 index 000000000..5f829afa4 --- /dev/null +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/EnumDescriptionOperationCustomizer.java @@ -0,0 +1,188 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * + * * * * + * * * + * * + * + */ + +package org.springdoc.core.customizers; + +import io.swagger.v3.oas.models.Operation; +import org.apache.commons.lang3.StringUtils; +import org.springdoc.core.annotations.EnumDescription; +import org.springdoc.core.service.AbstractRequestService; +import org.springframework.core.MethodParameter; +import org.springframework.web.method.HandlerMethod; + +import java.lang.reflect.Field; + +/** + * The type Enum description operation customizer. + * Automatically adds enum constants and descriptions to operation. + * when fields are annotated with {@link EnumDescription}. + * + * @author TAEWOOKK + */ +public class EnumDescriptionOperationCustomizer implements GlobalOperationCustomizer{ + + /** + * The constant DEFAULT_FIELD_NAME. + */ + private static final String DEFAULT_FIELD_NAME = "description"; + + @Override + public Operation customize(Operation operation, HandlerMethod handlerMethod) { + if (operation == null || handlerMethod == null) { + return operation; + } + + for (MethodParameter methodParameter : handlerMethod.getMethodParameters()) { + Class dtoClass = methodParameter.getParameterType(); + + if (!isValidDtoClass(dtoClass)) { + continue; + } + + String enumDescriptions = extractEnumDescriptionsFromDto(dtoClass); + if (StringUtils.isNotBlank(enumDescriptions)) { + String existingDescription = operation.getDescription(); + String newDescription = StringUtils.isNotBlank(existingDescription) + ? existingDescription + "\n\n" + enumDescriptions + : enumDescriptions; + operation.setDescription(newDescription); + } + } + + return operation; + } + + /** + * Is valid dto class boolean. + * + * @param clazz the clazz + * @return the boolean + */ + private boolean isValidDtoClass(Class clazz) { + return !clazz.isPrimitive() + && !clazz.isEnum() + && !clazz.isArray() + && !clazz.isInterface() + && !clazz.getName().startsWith("java.") + && !AbstractRequestService.isRequestTypeToIgnore(clazz); + } + + /** + * Extract enum descriptions from dto string. + * + * @param dtoClass the dto class + * @return the string + */ + private String extractEnumDescriptionsFromDto(Class dtoClass) { + if (dtoClass == null) { + return null; + } + + StringBuilder result = new StringBuilder(); + Class currentClass = dtoClass; + + while (currentClass != null && !currentClass.getName().startsWith("java.")) { + for (Field field : currentClass.getDeclaredFields()) { + EnumDescription annotation = field.getAnnotation(EnumDescription.class); + + if (annotation != null && field.getType().isEnum()) { + String enumDescriptionText = extractEnumDescription( + field.getType(), + annotation.fieldName(), + field.getName() + ); + + if (StringUtils.isNotBlank(enumDescriptionText)) { + if (!result.isEmpty()) { + result.append("\n\n"); + } + result.append(enumDescriptionText); + } + } + } + currentClass = currentClass.getSuperclass(); + } + + return !result.isEmpty() ? result.toString() : null; + } + + /** + * Extract enum description string. + * + * @param enumClass the enum class + * @param fieldName the field name + * @param fieldDisplayName the field display name + * @return the string + */ + private String extractEnumDescription(Class enumClass, + String fieldName, + String fieldDisplayName) { + Object[] enumConstants = enumClass.getEnumConstants(); + if (enumConstants == null || enumConstants.length == 0) { + return null; + } + + StringBuilder sb = new StringBuilder(); + sb.append("**").append(fieldDisplayName).append("**\n"); + + for (Object enumConstant : enumConstants) { + String enumKey = ((Enum) enumConstant).name(); + String description = getEnumDescription(enumConstant, fieldName); + + sb.append("- `").append(enumKey).append("`"); + if (StringUtils.isNotBlank(description)) { + sb.append(": ").append(description); + } + sb.append("\n"); + } + + return sb.toString(); + } + + /** + * Gets enum description string. + * + * @param enumConstant the enum constant + * @param fieldName the field name + * @return the string + */ + private String getEnumDescription(Object enumConstant, String fieldName) { + if (enumConstant == null) { + return ""; + } + + String targetFieldName = StringUtils.isNotBlank(fieldName) ? fieldName : DEFAULT_FIELD_NAME; + + try { + Field field = enumConstant.getClass().getDeclaredField(targetFieldName); + field.setAccessible(true); + Object value = field.get(enumConstant); + return value != null ? value.toString() : ""; + } catch (NoSuchFieldException | IllegalAccessException e) { + return ""; + } + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/HelloController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/HelloController.java new file mode 100644 index 000000000..9acc1a4e6 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/HelloController.java @@ -0,0 +1,44 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.api.v30.app244; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @PostMapping("/test") + public void test(@RequestBody TestRequest request) { + } + + @GetMapping("/test2") + public void test2(TestRequest2 request) { + } +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/Priority.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/Priority.java new file mode 100644 index 000000000..e0afc0da3 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/Priority.java @@ -0,0 +1,42 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.api.v30.app244; + +public enum Priority { + HIGH("High priority"), + LOW("Low priority"); + + private final String label; + + Priority(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/SpringDocApp244Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/SpringDocApp244Test.java new file mode 100644 index 000000000..f3db8cfa4 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/SpringDocApp244Test.java @@ -0,0 +1,37 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.api.v30.app244; + +import test.org.springdoc.api.v30.AbstractSpringDocV30Test; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +public class SpringDocApp244Test extends AbstractSpringDocV30Test { + + @SpringBootApplication + static class SpringDocTestApp {} +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/Status.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/Status.java new file mode 100644 index 000000000..a58ba166d --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/Status.java @@ -0,0 +1,42 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.api.v30.app244; + +public enum Status { + ACTIVE("Active status"), + INACTIVE("Inactive status"); + + private final String description; + + Status(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/TestRequest.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/TestRequest.java new file mode 100644 index 000000000..f80746a4f --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/TestRequest.java @@ -0,0 +1,42 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.api.v30.app244; + +import org.springdoc.core.annotations.EnumDescription; + +public class TestRequest { + @EnumDescription + private Status status; + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/TestRequest2.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/TestRequest2.java new file mode 100644 index 000000000..fd6cc28b4 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/TestRequest2.java @@ -0,0 +1,42 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.api.v30.app244; + +import org.springdoc.core.annotations.EnumDescription; + +public class TestRequest2 { + @EnumDescription(fieldName = "label") + private Priority priority; + + public Priority getPriority() { + return priority; + } + + public void setPriority(Priority priority) { + this.priority = priority; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app244.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app244.json new file mode 100644 index 000000000..3b82c44bd --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app244.json @@ -0,0 +1,91 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/test": { + "post": { + "tags": [ + "hello-controller" + ], + "description": "**status**\n- `ACTIVE`: Active status\n- `INACTIVE`: Inactive status\n", + "operationId": "test", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/test2": { + "get": { + "tags": [ + "hello-controller" + ], + "description": "**priority**\n- `HIGH`: High priority\n- `LOW`: Low priority\n", + "operationId": "test2", + "parameters": [ + { + "name": "request", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/TestRequest2" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "components": { + "schemas": { + "TestRequest": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "ACTIVE", + "INACTIVE" + ] + } + } + }, + "TestRequest2": { + "type": "object", + "properties": { + "priority": { + "type": "string", + "enum": [ + "HIGH", + "LOW" + ] + } + } + } + } + } +} diff --git a/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/HelloController.java b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/HelloController.java new file mode 100644 index 000000000..5b37966ba --- /dev/null +++ b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/HelloController.java @@ -0,0 +1,44 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.ui.app36; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @PostMapping("/test") + public void test(@RequestBody TestRequest request) { + } + + @GetMapping("/test2") + public void test2(TestRequest2 request) { + } +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/Priority.java b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/Priority.java new file mode 100644 index 000000000..20a46b930 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/Priority.java @@ -0,0 +1,42 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.ui.app36; + +public enum Priority { + HIGH("High priority"), + LOW("Low priority"); + + private final String label; + + Priority(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } +} diff --git a/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/SpringDocApp36Test.java b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/SpringDocApp36Test.java new file mode 100644 index 000000000..74d399ab2 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/SpringDocApp36Test.java @@ -0,0 +1,83 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.ui.app36; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.test.web.servlet.MvcResult; +import test.org.springdoc.ui.AbstractSpringDocTest; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class SpringDocApp36Test extends AbstractSpringDocTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void testEnumDescription() throws Exception { + MvcResult result = mockMvc.perform(get("/v3/api-docs")) + .andExpect(status().isOk()) + .andReturn(); + + String content = result.getResponse().getContentAsString(); + JsonNode jsonNode = objectMapper.readTree(content); + + String description = jsonNode.at("/paths/~1test/post/description").asText(""); + + assertTrue(description.contains("**status**"), "Should contain status enum description"); + assertTrue(description.contains("`ACTIVE`"), "Should contain ACTIVE enum value"); + assertTrue(description.contains("`INACTIVE`"), "Should contain INACTIVE enum value"); + assertTrue(description.contains("Active status"), "Should contain ACTIVE description"); + assertTrue(description.contains("Inactive status"), "Should contain INACTIVE description"); + } + + @Test + void testEnumDescriptionWithCustomFieldName() throws Exception { + MvcResult result = mockMvc.perform(get("/v3/api-docs")) + .andExpect(status().isOk()) + .andReturn(); + + String content = result.getResponse().getContentAsString(); + JsonNode jsonNode = objectMapper.readTree(content); + + String description = jsonNode.at("/paths/~1test2/get/description").asText(""); + + assertTrue(description.contains("**priority**"), "Should contain priority enum description"); + assertTrue(description.contains("`HIGH`"), "Should contain HIGH enum value"); + assertTrue(description.contains("`LOW`"), "Should contain LOW enum value"); + assertTrue(description.contains("High priority"), "Should contain HIGH label from custom field"); + assertTrue(description.contains("Low priority"), "Should contain LOW label from custom field"); + } + + @SpringBootApplication + static class SpringDocTestApp { + } +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/Status.java b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/Status.java new file mode 100644 index 000000000..cb882ede4 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/Status.java @@ -0,0 +1,42 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.ui.app36; + +public enum Status { + ACTIVE("Active status"), + INACTIVE("Inactive status"); + + private final String description; + + Status(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } +} diff --git a/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/TestRequest.java b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/TestRequest.java new file mode 100644 index 000000000..72a52d9db --- /dev/null +++ b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/TestRequest.java @@ -0,0 +1,42 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.ui.app36; + +import org.springdoc.core.annotations.EnumDescription; + +public class TestRequest { + @EnumDescription + private Status status; + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } +} diff --git a/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/TestRequest2.java b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/TestRequest2.java new file mode 100644 index 000000000..89beaf23e --- /dev/null +++ b/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app36/TestRequest2.java @@ -0,0 +1,42 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * * + * * * * * + * * * * + * * * + * + */ + +package test.org.springdoc.ui.app36; + +import org.springdoc.core.annotations.EnumDescription; + +public class TestRequest2 { + @EnumDescription(fieldName = "label") + private Priority priority; + + public Priority getPriority() { + return priority; + } + + public void setPriority(Priority priority) { + this.priority = priority; + } +}