springfox(swagger2)不适用于GsonHttpMessageConverterConfig

问题描述 投票:7回答:5

我想要构建的是一个spring-boot(v1.2.3)应用程序,并使用SpringFox(swagger2)v2.0.0公开我的Rest API

我的Swagger Spring配置

@EnableSwagger2
@Configuration
public class SwaggerConfig {

    @Bean
    public Docket myApi() {
        return new Docket(DocumentationType.SWAGGER_2)
            .genericModelSubstitutes(DeferredResult.class)
            .useDefaultResponseMessages(false)
            .forCodeGeneration(false)
            .pathMapping("/my-prj");
    }

}

我需要使用gson将我的pojo转换为json,我这样做:

@Configuration
public class GsonHttpMessageConverterConfig {

    @Bean
    public GsonHttpMessageConverter gsonHttpMessageConverter(Gson gson) {
        GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
        converter.setGson(gson);
        return converter;
    }
}

麻烦的是,如果使用GsonHttpMessageConverter,swagger v2会生成错误的json:

{
"value": "{\"swagger\":\"2.0\",\"info\":{\"description\":\"Api Documentation\",\"version\":\"1.0\",\"title\":\"Api Documentation\",\"termsOfService\":\"urn:tos\",\"contact\":{\"name\":\"Contact Email\"},\"license\":{\"name\":\"Apache 2.0\",\"url\":\"http:
...

JSON以value为前缀,真正的JSON成为转义字符串。

如果不使用GsonHttpMessageConverter,应该如何:

{
"swagger": "2.0",
"info": {
"description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a 
...

有没有一个解决方案来创建一个没有价值和逃避的正确的swagger JSON?

spring-boot gson swagger springfox
5个回答
28
投票

我自己解决了这个问题:

问题在于序列化这个类:

package springfox.documentation.spring.web.json;

import com.fasterxml.jackson.annotation.JsonRawValue;
import com.fasterxml.jackson.annotation.JsonValue;

public class Json {
  private final String value;

  public Json(String value) {
    this.value = value;
  }

  @JsonValue
  @JsonRawValue
  public String value() {
    return value;
  }
}

序列化它是正确的我实现了一个SpringfoxJsonToGsonAdapter并将其添加到我的gson配置:

适配器:

public class SpringfoxJsonToGsonAdapter implements JsonSerializer<Json> {

    @Override
    public JsonElement serialize(Json json, Type type, JsonSerializationContext context) {
        final JsonParser parser = new JsonParser();
        return parser.parse(json.value());
    }
} 

gson配置:

@Configuration
public class GsonHttpMessageConverterConfig {

    @Bean
    public GsonHttpMessageConverter gsonHttpMessageConverter() {
        GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
        converter.setGson(gson());
        return converter;
    }

    private Gson gson() {
        final GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter());
        return builder.create();
    }
}

1
投票

遇到类似的问题,但发现了一个稍微不同的解决方案,也使用上面提到的序列化器。

我们定义一个Bean,以便能够自动装配Gson对象。为了解决Swagger的问题,重要的是还要为Json类添加“registerTypeAdapter”。

@Configuration
public class GsonConfiguration {
   @Bean
   public Gson gson() {
      return new GsonBuilder().registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter()).create();
   }
}

SpringfoxJsonToGsonAdapter的内容与上面相同,仅为了完整性而在此处列出。

public class SpringfoxJsonToGsonAdapter implements JsonSerializer<Json> {
    @Override
    public JsonElement serialize(Json json, Type type, JsonSerializationContext context) {
        final JsonParser parser = new JsonParser();
        return parser.parse(json.value());
    }
}

对于使用Gson对象,只需执行以下操作:

@Component
public class Foobar {
   @Autowired
   Gson gson;

   @Autowired
   public Foobar() {
      // ... some constructor work ...
   }

   public void someMethod() {
      System.out.println(gson.toJson(...)); // Fill in some object ;-)
   }
}

1
投票

这是Oleg Majewski解决了转换为Kotlin的SpringFox + Gson问题的解决方案:

internal class SpringfoxJsonToGsonAdapter : JsonSerializer<Json> {

    override fun serialize(json: Json, type: Type, context: JsonSerializationContext): JsonElement
            = JsonParser().parse(json.value())

}

@Configuration
open class GsonHttpMessageConverterConfig {

    @Bean
    open fun gsonHttpMessageConverter(): GsonHttpMessageConverter {
        val converter = GsonHttpMessageConverter()
        converter.gson = gson()
        return converter
    }

    private fun gson(): Gson = GsonBuilder()
            .registerTypeAdapter(Json::class.java, SpringfoxJsonToGsonAdapter())
            .create()

}

0
投票

这与Oleg Majowski's的解决方案相同。我只是使用lambda函数来摆脱SpringfoxJsonToGsonAdapter类:

@Bean
public GsonHttpMessageConverter gsonHttpMessageConverter() {
    GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
    converter.setGson(gson());
    return converter;
}

private Gson gson() {
    final GsonBuilder builder = new GsonBuilder();
    JsonSerializer<Json> jsonSerializer =
            (Json json, Type type, JsonSerializationContext context) -> new JsonParser().parse(json.value());
    builder.registerTypeAdapter(Json.class, jsonSerializer);
    return builder.create();
}

-1
投票

我发现上述说明中遗漏的一些东西是包和进口。当我第一次尝试这个时,我使用了自己的包,但swagger-ui.html仍然说没有找到包。包装似乎是具体的。

下面的类与上面的完全相同,但我在整个类中包含了包名和导入。注册适配器与上面说明的相同。

首先是JSON类

package springfox.documentation.spring.web.json;

import com.fasterxml.jackson.annotation.*;

public class Json {
    private final String value;

    public Json(String value) {
    this.value = value;
    }

    @JsonValue
    @JsonRawValue
    public String value() {
    return value;
    }
}

和适配器类:

package springfox.documentation.spring.web.json;

import java.lang.reflect.Type;

import com.google.gson.*;

public class SpringfoxJsonToGsonAdapter implements com.google.gson.JsonSerializer<Json> {

    @Override
    public JsonElement serialize(Json json, Type type, JsonSerializationContext context) {
    final JsonParser parser = new JsonParser();
    return parser.parse(json.value());
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.