Skip to content

[kotlin][client] Add Jackson as serialization library #5236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bin/kotlin-client-all.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/sh

./bin/kotlin-client-gson.sh
./bin/kotlin-client-jackson.sh
./bin/kotlin-client-moshi-codegen.sh
./bin/kotlin-client-nonpublic.sh
./bin/kotlin-client-okhttp3.sh
Expand Down
32 changes: 32 additions & 0 deletions bin/kotlin-client-jackson.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh

SCRIPT="$0"
echo "# START SCRIPT: $SCRIPT"

while [ -h "$SCRIPT" ] ; do
ls=$(ls -ld "$SCRIPT")
link=$(expr "$ls" : '.*-> \(.*\)$')
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=$(dirname "$SCRIPT")/"$link"
fi
done

if [ ! -d "${APP_DIR}" ]; then
APP_DIR=$(dirname "$SCRIPT")/..
APP_DIR=$(cd "${APP_DIR}"; pwd)
fi

executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"

if [ ! -f "$executable" ]
then
mvn -B clean package
fi

# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -t modules/openapi-generator/src/main/resources/kotlin-client -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g kotlin --artifact-id kotlin-petstore-jackson --additional-properties serializationLibrary=jackson --additional-properties enumPropertyNaming=UPPERCASE -o samples/client/petstore/kotlin-jackson $@"

java ${JAVA_OPTS} -jar ${executable} ${ags}
2 changes: 1 addition & 1 deletion docs/generators/kotlin-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ sidebar_label: kotlin-server
|packageName|Generated artifact package name.| |org.openapitools.server|
|parcelizeModels|toggle "@Parcelize" for generated models| |null|
|serializableModel|boolean - toggle "implements Serializable" for generated models| |null|
|serializationLibrary|What serialization library to use: 'moshi' (default), or 'gson'| |moshi|
|serializationLibrary|What serialization library to use: 'moshi' (default), or 'gson' or 'jackson'| |moshi|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |null|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |null|
|sourceFolder|source folder for generated code| |src/main/kotlin|
Expand Down
2 changes: 1 addition & 1 deletion docs/generators/kotlin-spring.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ sidebar_label: kotlin-spring
|parcelizeModels|toggle "@Parcelize" for generated models| |null|
|reactive|use coroutines for reactive behavior| |false|
|serializableModel|boolean - toggle "implements Serializable" for generated models| |null|
|serializationLibrary|What serialization library to use: 'moshi' (default), or 'gson'| |moshi|
|serializationLibrary|What serialization library to use: 'moshi' (default), or 'gson' or 'jackson'| |moshi|
|serverPort|configuration the port in which the sever is to run on| |8080|
|serviceImplementation|generate stub service implementations that extends service interfaces. If this is set to true service interfaces will also be generated| |false|
|serviceInterface|generate service interfaces to go alongside controllers. In most cases this option would be used to update an existing project, so not to override implementations. Useful to help facilitate the generation gap pattern| |false|
Expand Down
2 changes: 1 addition & 1 deletion docs/generators/kotlin-vertx.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ sidebar_label: kotlin-vertx
|packageName|Generated artifact package name.| |org.openapitools|
|parcelizeModels|toggle "@Parcelize" for generated models| |null|
|serializableModel|boolean - toggle "implements Serializable" for generated models| |null|
|serializationLibrary|What serialization library to use: 'moshi' (default), or 'gson'| |moshi|
|serializationLibrary|What serialization library to use: 'moshi' (default), or 'gson' or 'jackson'| |moshi|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |null|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |null|
|sourceFolder|source folder for generated code| |src/main/kotlin|
Expand Down
2 changes: 1 addition & 1 deletion docs/generators/kotlin.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ sidebar_label: kotlin
|parcelizeModels|toggle "@Parcelize" for generated models| |null|
|requestDateConverter|JVM-Option. Defines in how to handle date-time objects that are used for a request (as query or parameter)|<dl><dt>**toJson**</dt><dd>[DEFAULT] Date formater option using a json converter.</dd><dt>**toString**</dt><dd>Use the 'toString'-method of the date-time object to retrieve the related string representation.</dd></dl>|toJson|
|serializableModel|boolean - toggle &quot;implements Serializable&quot; for generated models| |null|
|serializationLibrary|What serialization library to use: 'moshi' (default), or 'gson'| |moshi|
|serializationLibrary|What serialization library to use: 'moshi' (default), or 'gson' or 'jackson'| |moshi|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |null|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |null|
|sourceFolder|source folder for generated code| |src/main/kotlin|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@

public abstract class AbstractKotlinCodegen extends DefaultCodegen implements CodegenConfig {

public static final String SERIALIZATION_LIBRARY_DESC = "What serialization library to use: 'moshi' (default), or 'gson'";
public static final String SERIALIZATION_LIBRARY_DESC = "What serialization library to use: 'moshi' (default), or 'gson' or 'jackson'";

public enum SERIALIZATION_LIBRARY_TYPE {moshi, gson}
public enum SERIALIZATION_LIBRARY_TYPE {moshi, gson, jackson}

public static final String MODEL_MUTABLE = "modelMutable";
public static final String MODEL_MUTABLE_DESC = "Create mutable models";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,18 +323,26 @@ private void processJVMRetrofit2Library(String infrastructureFolder) {
private void addSupportingSerializerAdapters(final String infrastructureFolder) {
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/Serializer.kt.mustache", infrastructureFolder, "Serializer.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/ByteArrayAdapter.kt.mustache", infrastructureFolder, "ByteArrayAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateAdapter.kt.mustache", infrastructureFolder, "LocalDateAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateTimeAdapter.kt.mustache", infrastructureFolder, "LocalDateTimeAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/OffsetDateTimeAdapter.kt.mustache", infrastructureFolder, "OffsetDateTimeAdapter.kt"));


switch (getSerializationLibrary()) {
case moshi:
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/UUIDAdapter.kt.mustache", infrastructureFolder, "UUIDAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateAdapter.kt.mustache", infrastructureFolder, "LocalDateAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateTimeAdapter.kt.mustache", infrastructureFolder, "LocalDateTimeAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/OffsetDateTimeAdapter.kt.mustache", infrastructureFolder, "OffsetDateTimeAdapter.kt"));
break;

case gson:
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/DateAdapter.kt.mustache", infrastructureFolder, "DateAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateAdapter.kt.mustache", infrastructureFolder, "LocalDateAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateTimeAdapter.kt.mustache", infrastructureFolder, "LocalDateTimeAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/OffsetDateTimeAdapter.kt.mustache", infrastructureFolder, "OffsetDateTimeAdapter.kt"));
break;

case jackson:
//supportingFiles.add(new SupportingFile("jvm-common/infrastructure/DateAdapter.kt.mustache", infrastructureFolder, "DateAdapter.kt"));
break;

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ dependencies {
{{#gson}}
compile "com.google.code.gson:gson:2.8.6"
{{/gson}}
{{#jackson}}
compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.10.2"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.2"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.2"
{{/jackson}}
{{#jvm-okhttp3}}
compile "com.squareup.okhttp3:okhttp:3.12.6"
{{/jvm-okhttp3}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
{{/moshiCodeGen}}
{{/moshi}}
{{#jackson}}
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonFormat
{{/jackson}}
{{#parcelizeModels}}
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
Expand Down Expand Up @@ -53,6 +57,7 @@ import java.io.Serializable
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
{{#multiplatform}}@Serializable(with = {{nameInCamelCase}}.Serializer::class){{/multiplatform}}
{{#jackson}}{{#isPrimitiveType}}@JsonFormat(shape = JsonFormat.Shape.NATURAL){{/isPrimitiveType}}{{^isPrimitiveType}}@JsonFormat(shape = JsonFormat.Shape.OBJECT){{/isPrimitiveType}}{{/jackson}}
{{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{{nameInCamelCase}}}(val value: {{#isListContainer}}{{{ nestedType }}}{{/isListContainer}}{{^isListContainer}}{{{dataType}}}{{/isListContainer}}){
{{#allowableValues}}
{{#enumVars}}
Expand All @@ -63,6 +68,9 @@ import java.io.Serializable
{{#gson}}
@SerializedName(value={{{value}}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/gson}}
{{#jackson}}
@JsonProperty(value={{{value}}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/jackson}}
{{/multiplatform}}
{{#multiplatform}}
{{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,12 @@
{{#gson}}
@SerializedName("{{{vendorExtensions.x-base-name-literal}}}")
{{/gson}}
{{#jackson}}
{{#isDateTime}}
@JsonFormat
(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
{{/isDateTime}}
@JsonProperty("{{{vendorExtensions.x-base-name-literal}}}")
{{/jackson}}
{{/multiplatform}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isListContainer}}{{#isList}}kotlin.collections.List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{classname}}.{{{nameInCamelCase}}}>{{/isListContainer}}{{^isListContainer}}{{classname}}.{{{nameInCamelCase}}}{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isListContainer}}{{#isList}}kotlin.collections.List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{classname}}.{{{nameInCamelCase}}}>{{/isListContainer}}{{^isListContainer}}{{classname}}.{{{nameInCamelCase}}}{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@
{{#gson}}
@SerializedName("{{{vendorExtensions.x-base-name-literal}}}")
{{/gson}}
{{#jackson}}
@JsonProperty("{{{vendorExtensions.x-base-name-literal}}}")
{{/jackson}}
{{/multiplatform}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") @Required {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isListContainer}}{{#isList}}kotlin.collections.List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{classname}}.{{{nameInCamelCase}}}>{{/isListContainer}}{{^isListContainer}}{{classname}}.{{{nameInCamelCase}}}{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") @Required {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isListContainer}}{{#isList}}kotlin.collections.List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{classname}}.{{{nameInCamelCase}}}>{{/isListContainer}}{{^isListContainer}}{{classname}}.{{{nameInCamelCase}}}{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import kotlinx.serialization.internal.CommonEnumSerializer
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
{{#multiplatform}}@Serializable(with = {{classname}}.Serializer::class){{/multiplatform}}
{{#jackson}}@JsonFormat(shape = JsonFormat.Shape.OBJECT){{/jackson}}
{{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{classname}}(val value: {{{dataType}}}){

{{#allowableValues}}{{#enumVars}}
Expand All @@ -26,6 +27,9 @@ import kotlinx.serialization.internal.CommonEnumSerializer
{{#gson}}
@SerializedName(value = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}})
{{/gson}}
{{#jackson}}
@JsonProperty(value = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}})
{{/jackson}}
{{/multiplatform}}
{{#isListContainer}}
{{#isList}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ import org.threeten.bp.format.DateTimeFormatter
}
}
}
{{/gson}}
{{/gson}}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ import org.threeten.bp.OffsetDateTime
{{/threetenbp}}
import java.util.UUID
{{/gson}}
{{#jackson}}
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
{{/jackson}}
import java.util.Date

{{#nonPublicApi}}internal {{/nonPublicApi}}object Serializer {
Expand Down Expand Up @@ -57,4 +64,11 @@ import java.util.Date
gsonBuilder.create()
}
{{/gson}}
{{#jackson}}
@JvmStatic
val jacksonObjectMapper: ObjectMapper = jacksonObjectMapper()
.registerModule(Jdk8Module())
.registerModule(JavaTimeModule())
.setSerializationInclusion(JsonInclude.Include.NON_ABSENT)
{{/jackson}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,13 @@ import java.io.File
{{#gson}}
MediaType.parse(mediaType), Serializer.gson.toJson(content, T::class.java)
{{/gson}}
{{#jackson}}
MediaType.parse(mediaType), Serializer.jackson.toJson(content, T::class.java)
{{/jackson}}
)
{{/jvm-okhttp3}}
{{#jvm-okhttp4}}
mediaType == JsonMediaType -> {{#moshi}}Serializer.moshi.adapter(T::class.java).toJson(content){{/moshi}}{{#gson}}Serializer.gson.toJson(content, T::class.java){{/gson}}.toRequestBody(
mediaType == JsonMediaType -> {{#moshi}}Serializer.moshi.adapter(T::class.java).toJson(content){{/moshi}}{{#gson}}Serializer.gson.toJson(content, T::class.java){{/gson}}{{#jackson}}Serializer.jacksonObjectMapper.writeValueAsString(content){{/jackson}}.toRequestBody(
mediaType.toMediaTypeOrNull()
)
{{/jvm-okhttp4}}
Expand All @@ -99,7 +102,7 @@ import java.io.File
return null
}
return when(mediaType) {
JsonMediaType -> {{#moshi}}Serializer.moshi.adapter(T::class.java).fromJson(bodyContent){{/moshi}}{{#gson}}Serializer.gson.fromJson(bodyContent, T::class.java){{/gson}}
JsonMediaType -> {{#moshi}}Serializer.moshi.adapter(T::class.java).fromJson(bodyContent){{/moshi}}{{#gson}}Serializer.gson.fromJson(bodyContent, T::class.java){{/gson}}{{#jackson}}Serializer.jacksonObjectMapper.readValue(bodyContent, T::class.java){{/jackson}}
else -> throw UnsupportedOperationException("responseBody currently only supports JSON body.")
}
}
Expand Down Expand Up @@ -146,15 +149,15 @@ import java.io.File
{{#isBasicBearer}}
if (requestConfig.headers[Authorization].isNullOrEmpty()) {
accessToken?.let { accessToken ->
requestConfig.headers[Authorization] = "Bearer " + accessToken
requestConfig.headers[Authorization] = "Bearer $accessToken"
}
}
{{/isBasicBearer}}
{{/isBasic}}
{{#isOAuth}}
if (requestConfig.headers[Authorization].isNullOrEmpty()) {
accessToken?.let { accessToken ->
requestConfig.headers[Authorization] = "Bearer " + accessToken
requestConfig.headers[Authorization] = "Bearer $accessToken "
}
}
{{/isOAuth}}
Expand Down Expand Up @@ -251,6 +254,7 @@ import java.io.File
}
}

{{^jackson}}
protected inline fun <reified T: Any> parseDateToQueryString(value : T): String {
{{#toJson}}
/*
Expand All @@ -270,4 +274,5 @@ import java.io.File
return value.toString()
{{/toJson}}
}
{{/jackson}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ open class ApiClient(val baseUrl: String) {
}
if (requestConfig.headers[Authorization].isNullOrEmpty()) {
accessToken?.let { accessToken ->
requestConfig.headers[Authorization] = "Bearer " + accessToken
requestConfig.headers[Authorization] = "Bearer $accessToken "
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@ import com.google.gson.annotations.SerializedName

data class ApiResponse (
@SerializedName("code")
val code: kotlin.Int? = null,
val code: kotlin.Int? = null
,
@SerializedName("type")
val type: kotlin.String? = null,
val type: kotlin.String? = null
,
@SerializedName("message")
val message: kotlin.String? = null

)

Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import com.google.gson.annotations.SerializedName

data class Category (
@SerializedName("id")
val id: kotlin.Long? = null,
val id: kotlin.Long? = null
,
@SerializedName("name")
val name: kotlin.String? = null

)

Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,32 @@ import com.google.gson.annotations.SerializedName

data class Order (
@SerializedName("id")
val id: kotlin.Long? = null,
val id: kotlin.Long? = null
,
@SerializedName("petId")
val petId: kotlin.Long? = null,
val petId: kotlin.Long? = null
,
@SerializedName("quantity")
val quantity: kotlin.Int? = null,
val quantity: kotlin.Int? = null
,
@SerializedName("shipDate")
val shipDate: java.time.OffsetDateTime? = null,
val shipDate: java.time.OffsetDateTime? = null
,
/* Order Status */
@SerializedName("status")
val status: Order.Status? = null,
val status: Order.Status? = null
,
@SerializedName("complete")
val complete: kotlin.Boolean? = null

) {

/**
* Order Status
* Values: placed,approved,delivered
*/


enum class Status(val value: kotlin.String){
@SerializedName(value="placed") placed("placed"),
@SerializedName(value="approved") approved("approved"),
Expand Down
Loading