springfox(swagger2) does not work with GsonHttpMessageConverterConfig

眉间皱痕 提交于 2019-12-18 01:21:23

问题


What I am trying to build is a spring-boot (v1.2.3) application and expose my Rest API with SpringFox(swagger2) v2.0.0

my Swagger Spring config

@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");
    }

}

I need to use gson to convert my pojo's to json, and I do it this way:

@Configuration
public class GsonHttpMessageConverterConfig {

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

The trouble is that if using GsonHttpMessageConverter, swagger v2 generates a wrong 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:
...

the JSON is prefixed with value and the real JSON becomes an escaped string.

here is how it should be if not using 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 
...

Is there a solution to create a correct swagger JSON without value and escaping?


回答1:


solved the issue by myself:

the issue was with serializing this class:

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

to serialize it correct I implemented a SpringfoxJsonToGsonAdapter and added it to my gson config:

adapter:

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 config:

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



回答2:


Ran into a similar problem but found a little different solution which is also using the above mentioned serializer.

We define a Bean to be able to autowire Gson objects. For fixing the issue with Swagger the important part there is to also add "registerTypeAdapter" for the Json class.

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

The content of SpringfoxJsonToGsonAdapter is the same as above and only listed here for completeness.

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

For using the Gson object just do something like this:

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



回答3:


This is Oleg Majewski's solution for SpringFox + Gson problem translated to 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()

}



回答4:


This is the same solution as Oleg Majowski's. I am just getting rid of the SpringfoxJsonToGsonAdapter class using a lambda function instead:

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



回答5:


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

}


来源:https://stackoverflow.com/questions/30219946/springfoxswagger2-does-not-work-with-gsonhttpmessageconverterconfig

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!