【问题标题】:Swagger 2 accept xml instead of jsonSwagger 2 接受 xml 而不是 json
【发布时间】:2016-01-17 15:13:39
【问题描述】:

我有一个带有 spring boot 的项目,我想使用 swagger2 来记录我的 json web 服务。

我有这个配置:

@Configuration
@EnableSwagger2
public class Swagger2Config {

@Bean
public Docket welcomeMessageApi() {
    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            .select()
            .apis(RequestHandlerSelectors.any())
            .paths(PathSelectors.any())
            .build();
}

private ApiInfo apiInfo() {
    return new ApiInfoBuilder()
            .title("My API")
            .description("Lorem Ipsum is simply dummy text of ...")
            .termsOfServiceUrl("an url")
            .contact("contact")
            .license("")
            .licenseUrl("")
            .version("2.0")
            .build();
}

要阅读文档,我使用此链接:http://localhost:9081/v2/api-docs

在 swagger UI 中,它运行良好。但是当我直接在浏览器中尝试这个链接时,我有这个错误:

使用 Firebug,我发现它接受 XML 内容而不是 JSON 内容。

如何修改 swagger 配置以接受 JSON 内容?

【问题讨论】:

    标签: java spring-boot swagger-2.0 springfox


    【解决方案1】:

    您遇到问题是因为 Spring MVC 默认让服务器在浏览器中呈现 XML 而不是 JSON。 The official document说:

    要让服务器呈现 XML 而不是 JSON,您可能必须发送 Accept: text/xml 标头(或使用浏览器)。

    所以你需要做的就是让服务器在浏览器中呈现 JSON。

    当您深入浏览器中的请求时,您会看到请求标头:

    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    

    如果你调试到 spring boot 中,你会看到 spring mvc 将默认委托 HttpMessageConverters 包括 MappingJackson2XmlHttpMessageConverterMappingJackson2HttpMessageConverter

    MappingJackson2HttpMessageConverter 用于渲染 json,MappingJackson2XmlHttpMessageConverter 用于渲染 xml。

    它们都有一个字段supportedMediaTypes,表示支持哪些媒体类型。

    MappingJackson2HttpMessageConvertersupportedMediaTypes的值为:

    MappingJackson2XmlHttpMessageConvertersupportedMediaTypes的值为:

    MappingJackson2XmlHttpMessageConverter 中有一个 'text/xml;charset=UTF-8'。这就是浏览器渲染 json 的 xml 实例的原因。

    所以你需要添加一个支持'text/xml'的自定义MappingJackson2XmlHttpMessageConverter,例如:

        @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
            List<MediaType> list = new ArrayList<>();
            list.add(MediaType.APPLICATION_JSON_UTF8);
            list.add(new MediaType("text", "html", Charset.forName("UTF-8")));
            list.add(new MediaType("application", "*+json", Charset.forName("UTF-8")));
            converter.setSupportedMediaTypes(list);
            converters.add(converter);
        }
    }
    

    试试这个,浏览器将在浏览器中呈现 JSON 而不是 XML,一切正常!

    【讨论】:

    • 对我不起作用。实施此解决方案将服务器的响应 ContentType 从“application/xhtml...”更改为“text/html”,但没有将其更改为“application/json”:(
    【解决方案2】:

    对我有用的是更新 springfox-swagger2 和 springfox-swagger-ui 的 Maven 依赖项。

    对我来说最新的工作组合是:

        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.8.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
    

    【讨论】:

      【解决方案3】:

      当我尝试使用网络浏览器读取 Swagger API 时,我遇到了类似的问题。

      我用不同的方法解决了这个问题。
      如果您尝试使用其他一些工具(例如 PostMan 或 Curl 命令工具)调用端点,它将正确返回 JSON。

      看起来它只发生在网络浏览器中。

      如果您在 pom.xml 中有 Jackson XML 扩展,您可以尝试这种方法。 但如果需要返回 XML 数据作为响应,请另寻解决方案。

      这是我的方法,在下面添加扩展 WebMvcConfigurationSupport 类到项目源代码的配置。

      @Configuration
      public class MessageConverterConfiguration extends WebMvcConfigurationSupport {
          @Override
          public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
              HttpMessageConverter<?> target = null;
      
              for (HttpMessageConverter<?> converter : converters) { 
                  if (converter.getClass() == MappingJackson2XmlHttpMessageConverter.class) {
                      target = converter;
                  }
              }
      
              if (target != null) {
                  converters.remove(target);
              }
          }
      }
      
      1. 对于常规的 GET 类型请求,Web 浏览器向端点发送请求数据,包括请求标头中的“Accept”键,其中包含“xml”值。

      2. 此外,在服务器端,即使响应数据类型是 JSON,并且即使指定了 JSON 消息转换器,如果它与 JSON 数据兼容,Spring 也会首先选择 XML 消息转换器。

      3. 除此之外,选择过程基于请求中“接受”值的顺序。

        • 您可以在响应期间调试 AbstractMessageConverterMethodProcessor,尤其是 writeWithMessageConverters 方法 过程。
      4. 在选择过程中,Spring根据WebMvcConfigurationSupport在系统初始化过程中初始化的注册消息转换器列表,选择合适的转换器。

      5. WebMvcConfigurationSupport 提供了 extendMessageConverters 来扩展或修改转换器列表。

      6. 所以我尝试从列表中删除那个特殊的 XML 消息转换器,它可以工作。

      虽然上述解决方案对我有用,但您可能不会使用这种方法。

      如果您需要返回 XML 数据作为响应,请寻找其他解决方案。

      【讨论】:

        猜你喜欢
        • 2013-10-01
        • 1970-01-01
        • 2011-11-20
        • 1970-01-01
        • 1970-01-01
        • 2017-04-28
        • 1970-01-01
        • 1970-01-01
        • 2013-12-17
        相关资源
        最近更新 更多