diff --git a/docs/generators/java.md b/docs/generators/java.md
index 84b9056b7a0..e484573c4cc 100644
--- a/docs/generators/java.md
+++ b/docs/generators/java.md
@@ -56,3 +56,4 @@ sidebar_label: java
|useReflectionEqualsHashCode|Use org.apache.commons.lang3.builder for equals and hashCode in the models. WARNING: This will fail under a security manager, unless the appropriate permissions are set up correctly and also there's potential performance impact.| |false|
|caseInsensitiveResponseHeaders|Make API response's headers case-insensitive. Available on okhttp-gson, jersey2 libraries| |false|
|library|library template (sub-template) to use|
**jersey1**
HTTP client: Jersey client 1.19.x. JSON processing: Jackson 2.8.x. Enable Java6 support using '-DsupportJava6=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. IMPORTANT NOTE: jersey 1.x is no longer actively maintained so please upgrade to 'jersey2' or other HTTP libaries instead.
**jersey2**
HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.8.x
**feign**
HTTP client: OpenFeign 9.x or 10.x. JSON processing: Jackson 2.8.x. To enable OpenFeign 10.x, set the 'feignVersion' option to '10.x'
**okhttp-gson**
[DEFAULT] HTTP client: OkHttp 3.x. JSON processing: Gson 2.8.x. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'.
**retrofit**
HTTP client: OkHttp 2.x. JSON processing: Gson 2.x (Retrofit 1.9.0). IMPORTANT NOTE: retrofit1.x is no longer actively maintained so please upgrade to 'retrofit2' instead.
**retrofit2**
HTTP client: OkHttp 3.x. JSON processing: Gson 2.x (Retrofit 2.3.0). Enable the RxJava adapter using '-DuseRxJava[2]=true'. (RxJava 1.x or 2.x)
**resttemplate**
HTTP client: Spring RestTemplate 4.x. JSON processing: Jackson 2.8.x
**webclient**
HTTP client: Spring WebClient 5.x. JSON processing: Jackson 2.9.x
**resteasy**
HTTP client: Resteasy client 3.x. JSON processing: Jackson 2.8.x
**vertx**
HTTP client: VertX client 3.x. JSON processing: Jackson 2.8.x
**google-api-client**
HTTP client: Google API client 1.x. JSON processing: Jackson 2.8.x
**rest-assured**
HTTP client: rest-assured : 4.x. JSON processing: Gson 2.x. Only for Java8
**native**
HTTP client: Java native HttpClient. JSON processing: Jackson 2.9.x. Only for Java11+
|okhttp-gson|
+|serializationLibrary|Serialization library, default depends from the library|
**jackson**
Use Jackson as serialization library
**gson**
Use Gson as serialization library
|null|
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java
index 4faf042518f..fa3893d3219 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java
@@ -78,6 +78,10 @@ public class JavaClientCodegen extends AbstractJavaCodegen
public static final String RETROFIT_2 = "retrofit2";
public static final String VERTX = "vertx";
+ public static final String SERIALIZATION_LIBRARY = "serializationLibrary";
+ public static final String SERIALIZATION_LIBRARY_GSON = "gson";
+ public static final String SERIALIZATION_LIBRARY_JACKSON = "jackson";
+
protected String gradleWrapperPackage = "gradle.wrapper";
protected boolean useRxJava = false;
protected boolean useRxJava2 = false;
@@ -95,6 +99,8 @@ public class JavaClientCodegen extends AbstractJavaCodegen
protected boolean useReflectionEqualsHashCode = false;
protected boolean caseInsensitiveResponseHeaders = false;
protected String authFolder;
+ protected String serializationLibrary = null;
+
public JavaClientCodegen() {
super();
@@ -128,7 +134,6 @@ public class JavaClientCodegen extends AbstractJavaCodegen
cliOptions.add(CliOption.newBoolean(USE_REFLECTION_EQUALS_HASHCODE, "Use org.apache.commons.lang3.builder for equals and hashCode in the models. WARNING: This will fail under a security manager, unless the appropriate permissions are set up correctly and also there's potential performance impact."));
cliOptions.add(CliOption.newBoolean(CASE_INSENSITIVE_RESPONSE_HEADERS, "Make API response's headers case-insensitive. Available on " + OKHTTP_GSON + ", " + JERSEY2 + " libraries"));
-
supportedLibraries.put(JERSEY1, "HTTP client: Jersey client 1.19.x. JSON processing: Jackson 2.8.x. Enable Java6 support using '-DsupportJava6=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. IMPORTANT NOTE: jersey 1.x is no longer actively maintained so please upgrade to 'jersey2' or other HTTP libaries instead.");
supportedLibraries.put(JERSEY2, "HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.8.x");
supportedLibraries.put(FEIGN, "HTTP client: OpenFeign 9.x or 10.x. JSON processing: Jackson 2.8.x. To enable OpenFeign 10.x, set the 'feignVersion' option to '10.x'");
@@ -150,6 +155,12 @@ public class JavaClientCodegen extends AbstractJavaCodegen
cliOptions.add(libraryOption);
setLibrary(OKHTTP_GSON);
+ CliOption serializationLibrary = new CliOption(SERIALIZATION_LIBRARY, "Serialization library, default depends from the library");
+ Map serializationOptions = new HashMap<>();
+ serializationOptions.put(SERIALIZATION_LIBRARY_GSON, "Use Gson as serialization library");
+ serializationOptions.put(SERIALIZATION_LIBRARY_JACKSON, "Use Jackson as serialization library");
+ serializationLibrary.setEnum(serializationOptions);
+ cliOptions.add(serializationLibrary);
}
@Override
@@ -284,6 +295,10 @@ public class JavaClientCodegen extends AbstractJavaCodegen
"BeanValidationException.java"));
}
+ if (additionalProperties.containsKey(SERIALIZATION_LIBRARY)) {
+ setSerializationLibrary(additionalProperties.get(SERIALIZATION_LIBRARY).toString());
+ }
+
//TODO: add doc to retrofit1 and feign
if (FEIGN.equals(getLibrary()) || RETROFIT_1.equals(getLibrary())) {
modelDocTemplateFiles.remove("model_doc.mustache");
@@ -301,7 +316,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
}
if (FEIGN.equals(getLibrary())) {
- additionalProperties.put("jackson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
supportingFiles.add(new SupportingFile("ParamExpander.mustache", invokerFolder, "ParamExpander.java"));
supportingFiles.add(new SupportingFile("EncodingUtils.mustache", invokerFolder, "EncodingUtils.java"));
} else if (OKHTTP_GSON.equals(getLibrary()) || StringUtils.isEmpty(getLibrary())) {
@@ -316,48 +331,48 @@ public class JavaClientCodegen extends AbstractJavaCodegen
// NOTE: below moved to postProcessOpoerationsWithModels
//supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java"));
//supportingFiles.add(new SupportingFile("auth/RetryingOAuth.mustache", authFolder, "RetryingOAuth.java"));
- additionalProperties.put("gson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_GSON);
} else if (usesAnyRetrofitLibrary()) {
supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java"));
supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java"));
- additionalProperties.put("gson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_GSON);
if ("retrofit2".equals(getLibrary()) && !usePlayWS) {
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
}
} else if (JERSEY2.equals(getLibrary())) {
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
supportingFiles.add(new SupportingFile("ApiResponse.mustache", invokerFolder, "ApiResponse.java"));
- additionalProperties.put("jackson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
} else if (NATIVE.equals(getLibrary())) {
setJava8Mode(true);
additionalProperties.put("java8", "true");
- additionalProperties.put("jackson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
} else if (RESTEASY.equals(getLibrary())) {
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
- additionalProperties.put("jackson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
} else if (JERSEY1.equals(getLibrary())) {
- additionalProperties.put("jackson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
} else if (RESTTEMPLATE.equals(getLibrary())) {
- additionalProperties.put("jackson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));
} else if (WEBCLIENT.equals(getLibrary())) {
setJava8Mode(true);
additionalProperties.put("java8", "true");
- additionalProperties.put("jackson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
} else if (VERTX.equals(getLibrary())) {
typeMapping.put("file", "AsyncFile");
importMapping.put("AsyncFile", "io.vertx.core.file.AsyncFile");
setJava8Mode(true);
additionalProperties.put("java8", "true");
- additionalProperties.put("jackson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
apiTemplateFiles.put("apiImpl.mustache", "Impl.java");
apiTemplateFiles.put("rxApiImpl.mustache", ".java");
supportingFiles.remove(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
} else if (GOOGLE_API_CLIENT.equals(getLibrary())) {
- additionalProperties.put("jackson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
} else if (REST_ASSURED.equals(getLibrary())) {
- additionalProperties.put("gson", "true");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_GSON);
additionalProperties.put("convert", new CaseFormatLambda(LOWER_CAMEL, UPPER_UNDERSCORE));
apiTemplateFiles.put("api.mustache", ".java");
supportingFiles.add(new SupportingFile("ResponseSpecBuilders.mustache", invokerFolder, "ResponseSpecBuilders.java"));
@@ -415,16 +430,30 @@ public class JavaClientCodegen extends AbstractJavaCodegen
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
- additionalProperties.put("jackson", "true");
- additionalProperties.remove("gson");
+ forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
}
- if (additionalProperties.containsKey("jackson") && !NATIVE.equals(getLibrary())) {
- supportingFiles.add(new SupportingFile("RFC3339DateFormat.mustache", invokerFolder, "RFC3339DateFormat.java"));
- if ("threetenbp".equals(dateLibrary) && !usePlayWS) {
- supportingFiles.add(new SupportingFile("CustomInstantDeserializer.mustache", invokerFolder, "CustomInstantDeserializer.java"));
- }
+ if(getSerializationLibrary() == null) {
+ LOGGER.info("No serializationLibrary configured, using '"+SERIALIZATION_LIBRARY_GSON+"' as fallback");
+ setSerializationLibrary(SERIALIZATION_LIBRARY_GSON);
}
+ if(SERIALIZATION_LIBRARY_JACKSON.equals(getSerializationLibrary())) {
+ additionalProperties.put(SERIALIZATION_LIBRARY_JACKSON, "true");
+ additionalProperties.remove(SERIALIZATION_LIBRARY_GSON);
+ if (!NATIVE.equals(getLibrary())) {
+ supportingFiles.add(new SupportingFile("RFC3339DateFormat.mustache", invokerFolder, "RFC3339DateFormat.java"));
+ if ("threetenbp".equals(dateLibrary) && !usePlayWS) {
+ supportingFiles.add(new SupportingFile("CustomInstantDeserializer.mustache", invokerFolder, "CustomInstantDeserializer.java"));
+ }
+ }
+ } else if (SERIALIZATION_LIBRARY_GSON.equals(getSerializationLibrary())) {
+ additionalProperties.put(SERIALIZATION_LIBRARY_GSON, "true");
+ additionalProperties.remove(SERIALIZATION_LIBRARY_JACKSON);
+ } else {
+ additionalProperties.remove(SERIALIZATION_LIBRARY_JACKSON);
+ additionalProperties.remove(SERIALIZATION_LIBRARY_GSON);
+ }
+
}
private boolean usesAnyRetrofitLibrary() {
@@ -581,12 +610,12 @@ public class JavaClientCodegen extends AbstractJavaCodegen
if (!BooleanUtils.toBoolean(model.isEnum)) {
//final String lib = getLibrary();
//Needed imports for Jackson based libraries
- if (additionalProperties.containsKey("jackson")) {
+ if (additionalProperties.containsKey(SERIALIZATION_LIBRARY_JACKSON)) {
model.imports.add("JsonProperty");
model.imports.add("JsonValue");
model.imports.add("JsonInclude");
}
- if (additionalProperties.containsKey("gson")) {
+ if (additionalProperties.containsKey(SERIALIZATION_LIBRARY_GSON)) {
model.imports.add("SerializedName");
model.imports.add("TypeAdapter");
model.imports.add("JsonAdapter");
@@ -596,7 +625,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
}
} else { // enum class
//Needed imports for Jackson's JsonCreator
- if (additionalProperties.containsKey("jackson")) {
+ if (additionalProperties.containsKey(SERIALIZATION_LIBRARY_JACKSON)) {
model.imports.add("JsonValue");
model.imports.add("JsonCreator");
}
@@ -607,7 +636,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
public Map postProcessModelsEnum(Map objs) {
objs = super.postProcessModelsEnum(objs);
//Needed import for Gson based libraries
- if (additionalProperties.containsKey("gson")) {
+ if (additionalProperties.containsKey(SERIALIZATION_LIBRARY_GSON)) {
List