Skip to content

Commit 462f450

Browse files
authored
[kotlin] Map file and binary to ByteArray (#19840)
* [kotlin] Map file and binary to ByteArray * [kotlin] Map file and binary to ByteArray
1 parent 185c063 commit 462f450

File tree

26 files changed

+358
-5
lines changed
  • bin/configs
  • docs/generators
  • modules/openapi-generator/src/main
  • samples/client
    • others/kotlin-jvm-okhttp-parameter-tests/src/main/kotlin/org/openapitools/client/infrastructure
    • petstore
      • kotlin-allOff-discriminator/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-array-simple-string-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-bigdecimal-default-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-default-values-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-gson/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-jackson/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-jvm-okhttp4-coroutines/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-kotlinx-datetime/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-modelMutable/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-moshi-codegen/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-name-parameter-mappings/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-nonpublic/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-nullable/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-string
      • kotlin-threetenbp/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure
      • kotlin/src/main/kotlin/org/openapitools/client/infrastructure

26 files changed

+358
-5
lines changed

bin/configs/kotlin-string.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ templateDir: modules/openapi-generator/src/main/resources/kotlin-client
55
additionalProperties:
66
artifactId: kotlin-petstore-string
77
serializableModel: "true"
8+
mapFileBinaryToByteArray: "true"
89
sortModelPropertiesByRequiredFlag: "false"
910
sortParamsByRequiredFlag: "false"
1011
dateLibrary: string

docs/generators/kotlin.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
3131
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
3232
|idea|Add IntellJ Idea plugin and mark Kotlin main and test folders as source folders.| |false|
3333
|library|Library template (sub-template) to use|<dl><dt>**jvm-ktor**</dt><dd>Platform: Java Virtual Machine. HTTP client: Ktor 1.6.7. JSON processing: Gson, Jackson (default).</dd><dt>**jvm-okhttp4**</dt><dd>[DEFAULT] Platform: Java Virtual Machine. HTTP client: OkHttp 4.2.0 (Android 5.0+ and Java 8+). JSON processing: Moshi 1.8.0.</dd><dt>**jvm-spring-webclient**</dt><dd>Platform: Java Virtual Machine. HTTP: Spring 5 (or 6 with useSpringBoot3 enabled) WebClient. JSON processing: Jackson.</dd><dt>**jvm-spring-restclient**</dt><dd>Platform: Java Virtual Machine. HTTP: Spring 6 RestClient. JSON processing: Jackson.</dd><dt>**jvm-retrofit2**</dt><dd>Platform: Java Virtual Machine. HTTP client: Retrofit 2.6.2.</dd><dt>**multiplatform**</dt><dd>Platform: Kotlin multiplatform. HTTP client: Ktor 1.6.7. JSON processing: Kotlinx Serialization: 1.2.1.</dd><dt>**jvm-volley**</dt><dd>Platform: JVM for Android. HTTP client: Volley 1.2.1. JSON processing: gson 2.8.9</dd><dt>**jvm-vertx**</dt><dd>Platform: Java Virtual Machine. HTTP client: Vert.x Web Client. JSON processing: Moshi, Gson or Jackson.</dd></dl>|jvm-okhttp4|
34+
|mapFileBinaryToByteArray|Map File and Binary to ByteArray (default: false)| |false|
3435
|modelMutable|Create mutable models| |false|
3536
|moshiCodeGen|Whether to enable codegen with the Moshi library. Refer to the [official Moshi doc](https://github.com/square/moshi#codegen) for more info.| |false|
3637
|nullableReturnType|Nullable return type| |false|

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,13 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
9393

9494
public static final String SUPPORT_ANDROID_API_LEVEL_25_AND_BELLOW = "supportAndroidApiLevel25AndBelow";
9595

96+
public static final String MAP_FILE_BINARY_TO_BYTE_ARRAY = "mapFileBinaryToByteArray";
97+
9698
public static final String GENERATE_ONEOF_ANYOF_WRAPPERS = "generateOneOfAnyOfWrappers";
9799

98100
protected static final String VENDOR_EXTENSION_BASE_NAME_LITERAL = "x-base-name-literal";
99101

102+
100103
@Setter protected String dateLibrary = DateLibrary.JAVA8.value;
101104
@Setter protected String requestDateConverter = RequestDateConverter.TO_JSON.value;
102105
@Setter protected String collectionType = CollectionType.LIST.value;
@@ -108,6 +111,7 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
108111
protected boolean generateRoomModels = false;
109112
@Setter protected String roomModelPackage = "";
110113
@Setter protected boolean omitGradleWrapper = false;
114+
@Setter protected boolean mapFileBinaryToByteArray = false;
111115
@Setter protected boolean generateOneOfAnyOfWrappers = true;
112116
@Getter @Setter protected boolean failOnUnknownProperties = false;
113117

@@ -269,6 +273,8 @@ public KotlinClientCodegen() {
269273

270274
cliOptions.add(CliOption.newBoolean(SUPPORT_ANDROID_API_LEVEL_25_AND_BELLOW, "[WARNING] This flag will generate code that has a known security vulnerability. It uses `kotlin.io.createTempFile` instead of `java.nio.file.Files.createTempFile` in order to support Android API level 25 and bellow. For more info, please check the following links https://github.com/OpenAPITools/openapi-generator/security/advisories/GHSA-23x4-m842-fmwf, https://github.com/OpenAPITools/openapi-generator/pull/9284"));
271275

276+
cliOptions.add(new CliOption(MAP_FILE_BINARY_TO_BYTE_ARRAY, "Map File and Binary to ByteArray (default: false)").defaultValue(Boolean.FALSE.toString()));
277+
272278
cliOptions.add(CliOption.newBoolean(GENERATE_ONEOF_ANYOF_WRAPPERS, "Generate oneOf, anyOf schemas as wrappers."));
273279

274280
CliOption serializationLibraryOpt = new CliOption(CodegenConstants.SERIALIZATION_LIBRARY, SERIALIZATION_LIBRARY_DESC);
@@ -437,6 +443,15 @@ public void processOpts() {
437443
additionalProperties.put(this.serializationLibrary.name(), true);
438444
}
439445

446+
if (additionalProperties.containsKey(MAP_FILE_BINARY_TO_BYTE_ARRAY)) {
447+
setMapFileBinaryToByteArray(convertPropertyToBooleanAndWriteBack(MAP_FILE_BINARY_TO_BYTE_ARRAY));
448+
}
449+
additionalProperties.put(MAP_FILE_BINARY_TO_BYTE_ARRAY, mapFileBinaryToByteArray);
450+
if (mapFileBinaryToByteArray) {
451+
typeMapping.put("file", "kotlin.ByteArray");
452+
typeMapping.put("binary", "kotlin.ByteArray");
453+
}
454+
440455
if (additionalProperties.containsKey(GENERATE_ONEOF_ANYOF_WRAPPERS)) {
441456
setGenerateOneOfAnyOfWrappers(Boolean.parseBoolean(additionalProperties.get(GENERATE_ONEOF_ANYOF_WRAPPERS).toString()));
442457
}

modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,21 @@ import com.squareup.moshi.adapter
8787
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
8888
}
8989

90+
/**
91+
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
92+
*
93+
* @param byteArray The given file
94+
* @return The guessed Content-Type
95+
*/
96+
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
97+
val contentType = try {
98+
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
99+
} catch (io: IOException) {
100+
"application/octet-stream"
101+
}
102+
return contentType
103+
}
104+
90105
/**
91106
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
92107
*
@@ -100,6 +115,7 @@ import com.squareup.moshi.adapter
100115

101116
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
102117
when {
118+
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
103119
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
104120
mediaType == FormDataMediaType ->
105121
MultipartBody.Builder()

samples/client/others/kotlin-jvm-okhttp-parameter-tests/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
5858
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
5959
}
6060

61+
/**
62+
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
63+
*
64+
* @param byteArray The given file
65+
* @return The guessed Content-Type
66+
*/
67+
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
68+
val contentType = try {
69+
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
70+
} catch (io: IOException) {
71+
"application/octet-stream"
72+
}
73+
return contentType
74+
}
75+
6176
/**
6277
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
6378
*
@@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
7186

7287
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
7388
when {
89+
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
7490
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
7591
mediaType == FormDataMediaType ->
7692
MultipartBody.Builder()

samples/client/petstore/kotlin-allOff-discriminator/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
5858
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
5959
}
6060

61+
/**
62+
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
63+
*
64+
* @param byteArray The given file
65+
* @return The guessed Content-Type
66+
*/
67+
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
68+
val contentType = try {
69+
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
70+
} catch (io: IOException) {
71+
"application/octet-stream"
72+
}
73+
return contentType
74+
}
75+
6176
/**
6277
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
6378
*
@@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
7186

7287
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
7388
when {
89+
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
7490
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
7591
mediaType == FormDataMediaType ->
7692
MultipartBody.Builder()

samples/client/petstore/kotlin-array-simple-string-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
5858
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
5959
}
6060

61+
/**
62+
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
63+
*
64+
* @param byteArray The given file
65+
* @return The guessed Content-Type
66+
*/
67+
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
68+
val contentType = try {
69+
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
70+
} catch (io: IOException) {
71+
"application/octet-stream"
72+
}
73+
return contentType
74+
}
75+
6176
/**
6277
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
6378
*
@@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
7186

7287
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
7388
when {
89+
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
7490
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
7591
mediaType == FormDataMediaType ->
7692
MultipartBody.Builder()

samples/client/petstore/kotlin-bigdecimal-default-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
5858
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
5959
}
6060

61+
/**
62+
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
63+
*
64+
* @param byteArray The given file
65+
* @return The guessed Content-Type
66+
*/
67+
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
68+
val contentType = try {
69+
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
70+
} catch (io: IOException) {
71+
"application/octet-stream"
72+
}
73+
return contentType
74+
}
75+
6176
/**
6277
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
6378
*
@@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
7186

7287
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
7388
when {
89+
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
7490
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
7591
mediaType == FormDataMediaType ->
7692
MultipartBody.Builder()

samples/client/petstore/kotlin-default-values-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
5858
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
5959
}
6060

61+
/**
62+
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
63+
*
64+
* @param byteArray The given file
65+
* @return The guessed Content-Type
66+
*/
67+
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
68+
val contentType = try {
69+
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
70+
} catch (io: IOException) {
71+
"application/octet-stream"
72+
}
73+
return contentType
74+
}
75+
6176
/**
6277
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
6378
*
@@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
7186

7287
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
7388
when {
89+
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
7490
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
7591
mediaType == FormDataMediaType ->
7692
MultipartBody.Builder()

samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
5858
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
5959
}
6060

61+
/**
62+
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
63+
*
64+
* @param byteArray The given file
65+
* @return The guessed Content-Type
66+
*/
67+
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
68+
val contentType = try {
69+
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
70+
} catch (io: IOException) {
71+
"application/octet-stream"
72+
}
73+
return contentType
74+
}
75+
6176
/**
6277
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
6378
*
@@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
7186

7287
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
7388
when {
89+
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
7490
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
7591
mediaType == FormDataMediaType ->
7692
MultipartBody.Builder()

0 commit comments

Comments
 (0)