10

我正在尝试构建的是一个 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 
...

有没有一种解决方案可以创建一个没有价值和转义的正确的招摇 JSON?

4

5 回答 5

30

自己解决了这个问题:

问题在于序列化这个类:

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();
    }
}
于 2015-05-13T16:33:22.980 回答
4

这是Oleg Majewski针对 SpringFox + Gson 问题的解决方案,翻译为 Kotlin:

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()

}
于 2017-10-08T16:35:59.827 回答
1

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

我们定义了一个能够自动装配 Gson 对象的 Bean。为了解决 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 ;-)
   }
}
于 2017-06-30T07:32:22.057 回答
0

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

@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();
}
于 2019-03-28T19:29:35.223 回答
-1

A couple of things I found missing with the above instructions is the package and imports. When I first tried this, I used my own packages but swagger-ui.html still said there were no packages found. It appears the package is specific.

The classes below are exactly the same as above, but I included the entire class with package names and imports. Registering the adapter is the same as documented above.

First the JSON class

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;
    }
}

and the adapter class:

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());
    }

}
于 2018-05-03T14:57:27.727 回答