【问题标题】:How to implement snake_case for Swagger documentation in spring-boot-starter-data-rest?如何在spring-boot-starter-data-rest中为Swagger文档实现snake_case?
【发布时间】:2018-12-27 22:51:57
【问题描述】:

我正在使用 swagger 作为 spring-boot-starter-data-rest 项目的文档。在 application.properties 文件中,我配置了: spring.jackson.property-naming-strategy=SNAKE_CASE 命名策略,但不幸的是,我在 swagger 文档中得到了 camelCase。但是,如果我将项目从 spring-boot-starter-data-rest 更改为 spring-boot-starter-web,则相同的配置正在工作。以下是我在 spring boot 2.1.1.RELEASE 中使用的依赖项。

<?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
            <modelVersion>4.0.0</modelVersion>
            <parent>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.1.1.RELEASE</version>
                <relativePath/> <!-- lookup parent from repository -->
            </parent>
            <groupId>com.example</groupId>
            <artifactId>demo1</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <name>demo1</name>
            <description>Demo project for Spring Boot</description>
            <properties>
                <java.version>1.8</java.version>
            </properties>
            <dependencies>
                <dependency>
                    <groupId>io.springfox</groupId>
                    <artifactId>springfox-swagger-ui</artifactId>
                    <version>2.9.2</version>
                </dependency>
                <dependency>
                    <groupId>io.springfox</groupId>
                    <artifactId>springfox-swagger2</artifactId>
                    <version>2.9.2</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-data-rest</artifactId>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </project>

application.properties

        spring.jackson.property-naming-strategy=SNAKE_CASE

包 com.example.demo1;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;

    @SpringBootApplication
    public class Demo1Application {

        public static void main(String[] args) {
            SpringApplication.run(Demo1Application.class, args);

        }

    }

Swagger 配置

    package com.example.demo1;

    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.PropertyNamingStrategy;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import 
    org.springframework.data.web.config.SpringDataJacksonConfiguration;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.service.Contact;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;

    import java.util.ArrayList;

    @Configuration
    @EnableSwagger2
    @Import({SpringDataJacksonConfiguration.class})
    public class SwaggerConfig {


        public static ApiInfo metaData(String info) {
            return new ApiInfo(info,
                    "Th",
                    "1.0", "httn.html",
                    new Contact("Thd", "", "thoom"), "decense",
                    "https", new ArrayList());
        }

        @Bean
        public Docket cashFlowApi() {
            return new Docket(DocumentationType.SWAGGER_2).groupName("-caching").select()
                    .apis(RequestHandlerSelectors.basePackage("com.example.demo1"))
                    .paths(PathSelectors.any())
                    .build()
                    .apiInfo(SwaggerConfig.metaData("BOcPI"));
        }
    }

存储控制器

    package com.example.demo1;

    import java.util.Arrays;
    import java.util.List;

    import io.swagger.annotations.ApiOperation;
    import io.swagger.annotations.ApiParam;
    import io.swagger.annotations.ApiResponse;
    import io.swagger.annotations.ApiResponses;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;


    @RestController
    @CrossOrigin
    public class StoreController {

        @GetMapping(value = "/v1/storeMap")
        @ApiOperation(value = "Returns the list of stores", notes = "Returns the list of stores with pagination.")
        @ApiResponses(value = {@ApiResponse(code = 200, message = "Successfully retrieved the stores list"),
                @ApiResponse(code = 204, message = "No content"), @ApiResponse(code = 206, message = "Partial Content"),
                @ApiResponse(code = 401, message = "You are not authorized to view the resource"),
                @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"),
                @ApiResponse(code = 404, message = "The resource you were trying to reach is not found"),
                @ApiResponse(code = 500, message = "A technical error happened")})

        public ResponseEntity<Store> getStore(
                @RequestParam(name = "country_code", required = false) @ApiParam(value = "the code)") String countryCode
                ) {

            return ResponseEntity.ok(new Store(1,"ZZ"));
        }

    }

现在有了这个配置,在 API POST 方法中需要的是snake_case,而在文档中,swagger 显示的是 camelCase。我没有选择从 snake_case 更改为 camelCase 或 spring-boot-starter-data-rest 更改为 spring-boot-starter-web。

【问题讨论】:

    标签: spring spring-boot swagger spring-data-rest springfox


    【解决方案1】:

    我找到了解决方案,问题出在对象映射器上:

        @Configuration
        public class ObjectMapperAutoConfiguration implements WebMvcConfigurer {
    
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                ObjectMapper objectMapper = null;
                for (HttpMessageConverter converter : converters) {
                    if (converter instanceof MappingJackson2HttpMessageConverter ) {
                        MappingJackson2HttpMessageConverter jacksonConverter =
                                ((MappingJackson2HttpMessageConverter) converter);
    
                        if (objectMapper == null) {
                            objectMapper = jacksonConverter.getObjectMapper();
                        } else {
                            jacksonConverter.setObjectMapper(objectMapper);
                        }
                    }
                }
            }
        }
    

    【讨论】:

      【解决方案2】:

      我也有一个 Spring Boot + Swagger 项目有同样的问题,但使用 Spring 的 io.swagger 包没有 Springfox 库并使用 Gradle 插件 com.benjaminsproule.swagger 生成文档。因此,为了解决这个问题,我添加了这一行 ModelConverters.getInstance().addConverter(new ModelResolver(objectMapper))(这是一个 hack,我没有使用官方 API,但它有效):

      package com.company.api;
      
      import com.fasterxml.jackson.databind.ObjectMapper;
      import io.swagger.converter.ModelConverters;
      import io.swagger.jackson.ModelResolver;
      import io.swagger.jaxrs.config.BeanConfig;
      import io.swagger.jaxrs.listing.*;
      import org.glassfish.jersey.server.ResourceConfig;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Component;
      import javax.annotation.PostConstruct;
      
      @Component
      public class SwaggerConfig extends ResourceConfig {
      
        @Autowired ObjectMapper objectMapper;
      
        @PostConstruct public void configureSwagger() {
          // Available at localhost:port/swagger.json
          this.register(ApiListingResource.class);
          this.register(SwaggerSerializers.class);
      
          BeanConfig config = new BeanConfig();
          config.setConfigId("api-springboot-jersey-swagger");
          config.setTitle("Company API");
          config.setResourcePackage("com.company.api");
          config.setPrettyPrint(true);
          config.setScan(true);
          // With this hack we inject into Swagger the same object mapper
          // used by Spring (spring.jackson.property-naming-strategy)
          ModelConverters.getInstance().addConverter(new ModelResolver(objectMapper));
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-11-11
        • 1970-01-01
        • 1970-01-01
        • 2022-11-10
        • 1970-01-01
        • 2019-06-23
        • 1970-01-01
        • 2021-01-18
        • 2021-02-09
        相关资源
        最近更新 更多