Reputation: 1019
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?
Upvotes: 10
Views: 9085
Reputation: 717
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();
}
Upvotes: 0
Reputation: 39
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());
}
}
Upvotes: -1
Reputation: 37896
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()
}
Upvotes: 4
Reputation: 633
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 ;-)
}
}
Upvotes: 1
Reputation: 1019
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();
}
}
Upvotes: 30