Skip to content

Commit b4dd675

Browse files
author
bnasslahsen
committed
Merge branch 'tdevilleduc-feature/schema-property-resolver'
2 parents a0f0cf9 + 53c4bc1 commit b4dd675

File tree

11 files changed

+193
-3
lines changed

11 files changed

+193
-3
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public final class Constants {
3838

3939
public static final String SPRINGDOC_ENABLED = "springdoc.api-docs.enabled";
4040

41+
public static final String SPRINGDOC_SCHEMA_RESOLVE_PROPERTIES = "springdoc.api-docs.resolve-schema-properties";
42+
4143
public static final String SPRINGDOC_CACHE_DISABLED = "springdoc.cache.disabled";
4244

4345
public static final String SPRINGDOC_SWAGGER_UI_ENABLED = "springdoc.swagger-ui.enabled";

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import io.swagger.v3.oas.models.info.Contact;
4545
import io.swagger.v3.oas.models.info.Info;
4646
import io.swagger.v3.oas.models.info.License;
47+
import io.swagger.v3.oas.models.media.Schema;
4748
import io.swagger.v3.oas.models.security.SecurityScheme;
4849
import io.swagger.v3.oas.models.servers.Server;
4950
import org.apache.commons.lang3.StringUtils;
@@ -226,8 +227,21 @@ public Operation buildTags(HandlerMethod handlerMethod, Operation operation, Ope
226227
return operation;
227228
}
228229

229-
private boolean isAutoTagClasses(Operation operation) {
230-
return CollectionUtils.isEmpty(operation.getTags()) && springDocConfigProperties.isAutoTagClasses();
230+
public Schema resolveProperties(Schema schema, PropertyResolverUtils propertyResolverUtils) {
231+
resolveProperty(schema::getName, schema::name, propertyResolverUtils);
232+
resolveProperty(schema::getTitle, schema::title, propertyResolverUtils);
233+
resolveProperty(schema::getDescription, schema::description, propertyResolverUtils);
234+
235+
Map<String, Schema> properties = schema.getProperties();
236+
if (!CollectionUtils.isEmpty(properties)) {
237+
Map<String, Schema> resolvedSchemas = properties.entrySet().stream().map(es -> {
238+
es.setValue(resolveProperties(es.getValue(), propertyResolverUtils));
239+
return es;
240+
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
241+
schema.setProperties(resolvedSchemas);
242+
}
243+
244+
return schema;
231245
}
232246

233247
public void setServerBaseUrl(String serverBaseUrl) {
@@ -376,6 +390,10 @@ private OpenAPIDefinition getApiDefClass(ClassPathScanningCandidateComponentProv
376390
return null;
377391
}
378392

393+
private boolean isAutoTagClasses(Operation operation) {
394+
return CollectionUtils.isEmpty(operation.getTags()) && springDocConfigProperties.isAutoTagClasses();
395+
}
396+
379397
private Set<io.swagger.v3.oas.annotations.security.SecurityScheme> getSecuritySchemesClasses(
380398
ClassPathScanningCandidateComponentProvider scanner, List<String> packagesToScan) {
381399
Set<io.swagger.v3.oas.annotations.security.SecurityScheme> apiSecurityScheme = new HashSet<>();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public PropertyResolverUtils(ConfigurableBeanFactory factory) {
2828
this.factory = factory;
2929
}
3030

31-
String resolve(String parameterProperty) {
31+
public String resolve(String parameterProperty) {
3232
return factory.resolveEmbeddedValue(parameterProperty);
3333
}
3434
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ public static class ApiDocs {
151151
*/
152152
private boolean enabled = true;
153153

154+
private boolean resolveSchemaProperties;
155+
154156
private Groups groups = new Groups();
155157

156158
public String getPath() {
@@ -176,6 +178,14 @@ public Groups getGroups() {
176178
public void setGroups(Groups groups) {
177179
this.groups = groups;
178180
}
181+
182+
public boolean isResolveSchemaProperties() {
183+
return resolveSchemaProperties;
184+
}
185+
186+
public void setResolveSchemaProperties(boolean resolveSchemaProperties) {
187+
this.resolveSchemaProperties = resolveSchemaProperties;
188+
}
179189
}
180190

181191
public static class Groups {

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,21 @@
2020

2121
import java.util.Collections;
2222
import java.util.List;
23+
import java.util.Map;
2324
import java.util.Optional;
2425

2526
import com.fasterxml.jackson.databind.node.ObjectNode;
2627
import io.swagger.v3.core.converter.ModelConverter;
28+
import io.swagger.v3.oas.models.Components;
2729
import io.swagger.v3.oas.models.OpenAPI;
2830
import io.swagger.v3.oas.models.media.ObjectSchema;
31+
import io.swagger.v3.oas.models.media.Schema;
2932
import org.springdoc.core.converters.AdditionalModelsConverter;
3033
import org.springdoc.core.converters.ModelConverterRegistrar;
3134
import org.springdoc.core.converters.PropertyCustomizingConverter;
3235
import org.springdoc.core.converters.ResponseSupportConverter;
3336
import org.springdoc.core.customizers.OpenApiBuilderCustomiser;
37+
import org.springdoc.core.customizers.OpenApiCustomiser;
3438
import org.springdoc.core.customizers.PropertyCustomizer;
3539

3640
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@@ -47,6 +51,7 @@
4751

4852
import static org.springdoc.core.Constants.SPRINGDOC_CACHE_DISABLED;
4953
import static org.springdoc.core.Constants.SPRINGDOC_ENABLED;
54+
import static org.springdoc.core.Constants.SPRINGDOC_SCHEMA_RESOLVE_PROPERTIES;
5055
import static org.springdoc.core.SpringDocUtils.getConfig;
5156

5257
@Configuration
@@ -124,6 +129,16 @@ public GenericParameterBuilder parameterBuilder(PropertyResolverUtils propertyRe
124129
return new GenericParameterBuilder(propertyResolverUtils);
125130
}
126131

132+
@Bean
133+
@ConditionalOnProperty(SPRINGDOC_SCHEMA_RESOLVE_PROPERTIES)
134+
public OpenApiCustomiser propertiesResolverForSchema(PropertyResolverUtils propertyResolverUtils, OpenAPIBuilder openAPIBuilder) {
135+
return openApi -> {
136+
Components components = openApi.getComponents();
137+
Map<String, Schema> schemas = components.getSchemas();
138+
schemas.values().forEach(schema -> openAPIBuilder.resolveProperties(schema, propertyResolverUtils));
139+
};
140+
}
141+
127142
static class ConditionOnCacheOrGroupedOpenApi extends AnyNestedCondition {
128143

129144
ConditionOnCacheOrGroupedOpenApi() {

springdoc-openapi-data-rest/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
<artifactId>querydsl-core</artifactId>
3030
<optional>true</optional>
3131
</dependency>
32+
<dependency>
33+
<groupId>jakarta.annotation</groupId>
34+
<artifactId>jakarta.annotation-api</artifactId>
35+
<optional>true</optional>
36+
</dependency>
3237
<dependency>
3338
<groupId>org.springdoc</groupId>
3439
<artifactId>springdoc-openapi-webmvc-core</artifactId>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package test.org.springdoc.api.app101;
2+
3+
import io.swagger.v3.oas.annotations.media.Content;
4+
import io.swagger.v3.oas.annotations.media.Schema;
5+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.web.bind.annotation.RequestMapping;
8+
import org.springframework.web.bind.annotation.RestController;
9+
10+
@RestController
11+
@RequestMapping("/hello")
12+
public class HelloController {
13+
14+
@GetMapping
15+
@ApiResponse(content = @Content(schema = @Schema(
16+
description = "${test.app101.operation.hello.response.schema.description}",
17+
implementation = HelloDTO.class)))
18+
public HelloDTO hello() {
19+
return new HelloDTO();
20+
}
21+
22+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package test.org.springdoc.api.app101;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import io.swagger.v3.oas.annotations.media.Schema;
5+
6+
@Schema(description = "${test.app101.schema.hello.description}")
7+
public class HelloDTO {
8+
9+
@Schema(description = "${test.app101.schema.hello.param.id.description}")
10+
private String id;
11+
12+
@JsonProperty("id")
13+
public String getId() {
14+
return id;
15+
}
16+
17+
public void setId(String id) {
18+
this.id = id;
19+
}
20+
21+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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.app101;
20+
21+
22+
import org.springframework.boot.autoconfigure.SpringBootApplication;
23+
import org.springframework.test.context.ActiveProfiles;
24+
import test.org.springdoc.api.AbstractSpringDocTest;
25+
26+
@ActiveProfiles("101")
27+
public class SpringDocApp101Test extends AbstractSpringDocTest {
28+
29+
@SpringBootApplication
30+
static class SpringDocTestApp {}
31+
32+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
test:
2+
app101:
3+
operation:
4+
hello:
5+
response:
6+
schema:
7+
description: Description of schema of api response hello
8+
schema:
9+
hello:
10+
description: Description of schema of hello entity
11+
param:
12+
id:
13+
description: Description of schema of param id for api hello
14+
springdoc:
15+
api-docs:
16+
resolve-schema-properties: true
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
"/hello": {
15+
"get": {
16+
"tags": [
17+
"hello-controller"
18+
],
19+
"operationId": "hello",
20+
"responses": {
21+
"default": {
22+
"description": "default response",
23+
"content": {
24+
"*/*": {
25+
"schema": {
26+
"$ref": "#/components/schemas/HelloDTO"
27+
}
28+
}
29+
}
30+
}
31+
}
32+
}
33+
}
34+
},
35+
"components": {
36+
"schemas": {
37+
"HelloDTO": {
38+
"type": "object",
39+
"properties": {
40+
"id": {
41+
"type": "string",
42+
"description": "Description of schema of param id for api hello"
43+
}
44+
},
45+
"description": "Description of schema of hello entity"
46+
}
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)