diff --git a/.github/workflows/samples-kotlin-client.yaml b/.github/workflows/samples-kotlin-client.yaml index 2a714bad3771..be87c6771fde 100644 --- a/.github/workflows/samples-kotlin-client.yaml +++ b/.github/workflows/samples-kotlin-client.yaml @@ -72,6 +72,7 @@ jobs: - samples/client/others/kotlin-jvm-okhttp-path-comments - samples/client/others/kotlin-integer-enum - samples/client/petstore/kotlin-allOf-discriminator-kotlinx-serialization + - samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization steps: - uses: actions/checkout@v5 - uses: actions/setup-java@v5 diff --git a/bin/configs/kotlin-oneOf-discriminator-kotlinx-serialization.yaml b/bin/configs/kotlin-oneOf-discriminator-kotlinx-serialization.yaml new file mode 100644 index 000000000000..1a77e90557cb --- /dev/null +++ b/bin/configs/kotlin-oneOf-discriminator-kotlinx-serialization.yaml @@ -0,0 +1,12 @@ +generatorName: kotlin +outputDir: samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization +inputSpec: modules/openapi-generator/src/test/resources/3_0/kotlin/polymorphism-oneof-discriminator.yaml +templateDir: modules/openapi-generator/src/main/resources/kotlin-client +additionalProperties: + artifactId: kotlin-oneOf-discriminator + serializableModel: "false" + dateLibrary: java8 + library: jvm-retrofit2 + enumUnknownDefaultCase: true + serializationLibrary: kotlinx_serialization + generateOneOfAnyOfWrappers: true diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java index e637234fb0f6..09b03e1a1f95 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.common.collect.ImmutableMap; import com.samskivert.mustache.Mustache; +import com.samskivert.mustache.Template; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import lombok.Getter; @@ -35,6 +36,9 @@ import org.slf4j.LoggerFactory; import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; import java.util.*; import java.util.function.Function; import java.util.regex.Pattern; @@ -1172,4 +1176,15 @@ protected void doDataTypeAssignment(final String returnType, DataTypeAssigner da } } } + + protected static abstract class CustomLambda implements Mustache.Lambda { + @Override + public void execute(Template.Fragment frag, Writer out) throws IOException { + final StringWriter tempWriter = new StringWriter(); + frag.execute(tempWriter); + out.write(formatFragment(tempWriter.toString())); + } + + public abstract String formatFragment(String fragment); + } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java index 39851411f9da..2bd880808a3b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java @@ -22,7 +22,6 @@ import lombok.Setter; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.*; -import org.openapitools.codegen.meta.features.*; import org.openapitools.codegen.model.ModelMap; import org.openapitools.codegen.model.ModelsMap; import org.openapitools.codegen.model.OperationMap; @@ -40,10 +39,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import com.samskivert.mustache.Mustache; import lombok.Getter; import lombok.Setter; -import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenModel; @@ -60,14 +57,7 @@ import org.openapitools.codegen.meta.features.SchemaSupportFeature; import org.openapitools.codegen.meta.features.SecurityFeature; import org.openapitools.codegen.meta.features.WireFormatFeature; -import org.openapitools.codegen.model.ModelMap; -import org.openapitools.codegen.model.ModelsMap; -import org.openapitools.codegen.model.OperationMap; -import org.openapitools.codegen.model.OperationsMap; import org.openapitools.codegen.templating.mustache.ReplaceAllLambda; -import org.openapitools.codegen.utils.ProcessUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import static java.util.Collections.sort; @@ -569,6 +559,7 @@ public void processOpts() { // as the parser interrupts that as a start of a multiline comment. // We replace paths like `/v1/foo/*` with `/v1/foo/<*>` to avoid this additionalProperties.put("sanitizePathComment", new ReplaceAllLambda("\\/\\*", "/<*>")); + additionalProperties.put("fnToOneOfWrapperName", new ToOneOfWrapperName()); } private void processDateLibrary() { @@ -974,11 +965,21 @@ public Map postProcessAllModels(Map objs) if (discriminator == null) { continue; } + + // When using generateOneOfAnyOfWrappers and encountering oneOf, we keep discriminator properties, + // because single entity can be referenced in multiple "parent" entities, + // so discriminator for one might not be discriminator for another. + boolean shouldKeepDiscriminatorField = generateOneOfAnyOfWrappers && cm.oneOf != null && !cm.oneOf.isEmpty(); + + if (shouldKeepDiscriminatorField) { + continue; + } + // Remove discriminator property from the base class, it is not needed in the generated code getAllVarProperties(cm).forEach(list -> list.removeIf(var -> var.name.equals(discriminator.getPropertyName()))); for (CodegenDiscriminator.MappedModel mappedModel : discriminator.getMappedModels()) { - // Add the mapping name to additionalProperties.disciminatorValue + // Add the mapping name to additionalProperties.discriminatorValue // The mapping name is used to define SerializedName, which in result makes derived classes // found by kotlinx-serialization during deserialization CodegenProperty additionalProperties = mappedModel.getModel().getAdditionalProperties(); @@ -996,7 +997,6 @@ public Map postProcessAllModels(Map objs) mappedModel.getModel().setHasVars(false); } } - } } } @@ -1141,6 +1141,13 @@ private void adjustEnumRefDefault(CodegenParameter param) { param.defaultValue = type + "." + param.enumDefaultValue; } + private class ToOneOfWrapperName extends CustomLambda { + @Override + public String formatFragment(String fragment) { + return toModelName(StringUtils.lowerCase(fragment)) + "Wrapper"; + } + } + @Override public void postProcess() { System.out.println("################################################################################"); diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache index a6423598c0b9..6986ff31e043 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache @@ -37,6 +37,28 @@ import kotlinx.serialization.builtins.serializer import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder {{/enumUnknownDefaultCase}} +{{^enumUnknownDefaultCase}} +{{#generateOneOfAnyOfWrappers}} +{{#discriminator}} +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +{{/discriminator}} +{{/generateOneOfAnyOfWrappers}} +{{/enumUnknownDefaultCase}} +{{#generateOneOfAnyOfWrappers}} +{{#discriminator}} +import kotlinx.serialization.SerializationException +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.json.JsonDecoder +import kotlinx.serialization.json.JsonEncoder +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive +{{/discriminator}} +{{/generateOneOfAnyOfWrappers}} {{#hasEnums}} {{/hasEnums}} {{/kotlinx_serialization}} @@ -57,7 +79,9 @@ import java.io.Serializable import {{roomModelPackage}}.{{classname}}RoomModel import {{packageName}}.infrastructure.ITransformForStorage {{/generateRoomModels}} +{{^kotlinx_serialization}} import java.io.IOException +{{/kotlinx_serialization}} /** * {{{description}}} @@ -66,12 +90,68 @@ import java.io.IOException {{#parcelizeModels}} @Parcelize {{/parcelizeModels}} +{{^generateOneOfAnyOfWrappers}} +{{^discriminator}} {{#multiplatform}}{{^discriminator}}@Serializable{{/discriminator}}{{/multiplatform}}{{#kotlinx_serialization}}{{#serializableModel}}@KSerializable{{/serializableModel}}{{^serializableModel}}@Serializable{{/serializableModel}}{{/kotlinx_serialization}}{{#moshi}}{{#moshiCodeGen}}@JsonClass(generateAdapter = true){{/moshiCodeGen}}{{/moshi}}{{#jackson}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{/jackson}} +{{/discriminator}} +{{/generateOneOfAnyOfWrappers}} +{{#kotlinx_serialization}} +{{#generateOneOfAnyOfWrappers}} +{{#discriminator}} +@Serializable(with = {{classname}}Serializer::class) +{{/discriminator}} +{{/generateOneOfAnyOfWrappers}} +{{/kotlinx_serialization}} {{#isDeprecated}} @Deprecated(message = "This schema is deprecated.") {{/isDeprecated}} {{>additionalModelTypeAnnotations}} +{{#kotlinx_serialization}} +{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}sealed interface {{classname}} { +{{#discriminator.mappedModels}} + @JvmInline + {{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}} value class {{#fnToOneOfWrapperName}}{{mappingName}}{{/fnToOneOfWrapperName}}(val value: {{modelName}}) : {{classname}} +{{/discriminator.mappedModels}} +} + +{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}object {{classname}}Serializer : KSerializer<{{classname}}> { + override val descriptor: SerialDescriptor = buildClassSerialDescriptor("{{classname}}") + + override fun serialize(encoder: Encoder, value: {{classname}}) { + require(encoder is JsonEncoder) + val jsonObject = when (value) { +{{#discriminator.mappedModels}} + is {{classname}}.{{#fnToOneOfWrapperName}}{{mappingName}}{{/fnToOneOfWrapperName}} -> { + val jsonMap = encoder.json.encodeToJsonElement({{modelName}}.serializer(), value.value).jsonObject.toMutableMap() + jsonMap["{{discriminator.propertyBaseName}}"] = JsonPrimitive("{{mappingName}}") + JsonObject(jsonMap) + } +{{/discriminator.mappedModels}} + } + encoder.encodeJsonElement(jsonObject) + } + + override fun deserialize(decoder: Decoder): {{classname}} { + require(decoder is JsonDecoder) + val element = decoder.decodeJsonElement().jsonObject + + val discriminatorValue = element["{{discriminator.propertyBaseName}}"]?.jsonPrimitive?.content + ?: throw SerializationException("Missing {{discriminator.propertyBaseName}} field") + + return when (discriminatorValue) { +{{#discriminator.mappedModels}} + "{{mappingName}}" -> { + val decoded = decoder.json.decodeFromJsonElement({{modelName}}.serializer(), element) + {{classname}}.{{#fnToOneOfWrapperName}}{{mappingName}}{{/fnToOneOfWrapperName}}(decoded) + } +{{/discriminator.mappedModels}} + else -> throw SerializationException("Unknown {{classname}} {{discriminator.propertyBaseName}}: $discriminatorValue") + } + } +} +{{/kotlinx_serialization}} +{{^kotlinx_serialization}} {{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}data class {{classname}}(var actualInstance: Any? = null) { {{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}class CustomTypeAdapterFactory : TypeAdapterFactory { @@ -332,4 +412,5 @@ import java.io.IOException } } } -} \ No newline at end of file +} +{{/kotlinx_serialization}} \ No newline at end of file diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java index 11a1b6f6f4fc..c4bedf76c279 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java @@ -43,7 +43,7 @@ import java.util.Map; import static org.openapitools.codegen.CodegenConstants.*; -import static org.openapitools.codegen.TestUtils.assertFileContains; +import static org.openapitools.codegen.languages.KotlinClientCodegen.GENERATE_ONEOF_ANYOF_WRAPPERS; @SuppressWarnings("static-method") public class KotlinClientCodegenModelTest { @@ -502,7 +502,7 @@ private void givenSchemaObjectPropertyNameContainsDollarSignWhenGenerateThenDoll // properties.put(CodegenConstants.LIBRARY, ClientLibrary.JVM_KTOR); properties.put(CodegenConstants.ENUM_PROPERTY_NAMING, CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.UPPERCASE.toString()); properties.put(SERIALIZATION_LIBRARY, KotlinClientCodegen.SERIALIZATION_LIBRARY_TYPE.gson.toString()); - properties.put(KotlinClientCodegen.GENERATE_ONEOF_ANYOF_WRAPPERS, true); + properties.put(GENERATE_ONEOF_ANYOF_WRAPPERS, true); properties.put(API_PACKAGE, "com.toasttab.service.scim.api"); properties.put(MODEL_PACKAGE, "com.toasttab.service.scim.models"); properties.put(PACKAGE_NAME, "com.toasttab.service.scim"); @@ -661,6 +661,7 @@ public void emptyModelKotlinxSerializationTest() throws IOException { .setGeneratorName("kotlin") .setAdditionalProperties(new HashMap<>() {{ put(CodegenConstants.MODEL_PACKAGE, "model"); + put(GENERATE_ONEOF_ANYOF_WRAPPERS, false); put(SERIALIZATION_LIBRARY, "kotlinx_serialization"); }}) .setInputSpec("src/test/resources/3_0/kotlin/empty-model.yaml") diff --git a/modules/openapi-generator/src/test/resources/3_0/kotlin/polymorphism-oneof-discriminator.yaml b/modules/openapi-generator/src/test/resources/3_0/kotlin/polymorphism-oneof-discriminator.yaml new file mode 100644 index 000000000000..e134690cacf0 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/kotlin/polymorphism-oneof-discriminator.yaml @@ -0,0 +1,83 @@ +openapi: 3.0.1 +info: + title: Example + description: An example + version: '0.1' + contact: + email: contact@example.org + url: 'https://example.org' +servers: + - url: http://example.org +tags: + - name: bird +paths: + '/v1/bird/{id}': + get: + tags: + - bird + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/animal' + operationId: get-bird + parameters: + - schema: + type: string + format: uuid + name: id + in: path + required: true +components: + schemas: + animal: + title: An animal + oneOf: + - $ref: '#/components/schemas/bird' + - $ref: '#/components/schemas/robobird' + discriminator: + propertyName: discriminator + mapping: + BIRD: '#/components/schemas/bird' + ROBOBIRD: '#/components/schemas/robobird' + another_animal: + title: Another animal + oneOf: + - $ref: '#/components/schemas/bird' + - $ref: '#/components/schemas/robobird' + discriminator: + propertyName: another_discriminator + mapping: + ANOTHER_BIRD: '#/components/schemas/bird' + ANOTHER_ROBOBIRD: '#/components/schemas/robobird' + + bird: + title: A bird + required: + - discriminator + - another_discriminator + properties: + propertyA: + type: string + sameNameProperty: + type: integer + discriminator: + type: string + another_discriminator: + type: string + robobird: + title: A robo-bird + required: + - discriminator + - another_discriminator + properties: + propertyB: + type: string + sameNameProperty: + type: string + discriminator: + type: string + another_discriminator: + type: string diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/.openapi-generator-ignore b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/.openapi-generator/FILES b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/.openapi-generator/FILES new file mode 100644 index 000000000000..a4e5d6ad4eea --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/.openapi-generator/FILES @@ -0,0 +1,34 @@ +README.md +build.gradle +docs/Animal.md +docs/AnotherAnimal.md +docs/Bird.md +docs/BirdApi.md +docs/Robobird.md +gradle/wrapper/gradle-wrapper.jar +gradle/wrapper/gradle-wrapper.properties +gradlew +gradlew.bat +proguard-rules.pro +settings.gradle +src/main/kotlin/org/openapitools/client/apis/BirdApi.kt +src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/CollectionFormats.kt +src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/ResponseExt.kt +src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt +src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt +src/main/kotlin/org/openapitools/client/models/Animal.kt +src/main/kotlin/org/openapitools/client/models/AnotherAnimal.kt +src/main/kotlin/org/openapitools/client/models/Bird.kt +src/main/kotlin/org/openapitools/client/models/Robobird.kt diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/.openapi-generator/VERSION b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/.openapi-generator/VERSION new file mode 100644 index 000000000000..2fb556b60635 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.18.0-SNAPSHOT diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/README.md b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/README.md new file mode 100644 index 000000000000..ff539c8cb14e --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/README.md @@ -0,0 +1,70 @@ +# org.openapitools.client - Kotlin client library for Example + +An example + +## Overview +This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate an API client. + +- API version: 0.1 +- Package version: +- Generator version: 7.18.0-SNAPSHOT +- Build package: org.openapitools.codegen.languages.KotlinClientCodegen +For more information, please visit [https://example.org](https://example.org) + +## Requires + +* Kotlin 2.2.20 +* Gradle 8.14 + +## Build + +First, create the gradle wrapper script: + +``` +gradle wrapper +``` + +Then, run: + +``` +./gradlew check assemble +``` + +This runs all tests and packages the library. + +## Features/Implementation Notes + +* Supports JSON inputs/outputs, File inputs, and Form inputs. +* Supports collection formats for query parameters: csv, tsv, ssv, pipes. +* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions. +* Implementation of ApiClient is intended to reduce method counts, specifically to benefit Android targets. + + +## Documentation for API Endpoints + +All URIs are relative to *http://example.org* + +| Class | Method | HTTP request | Description | +| ------------ | ------------- | ------------- | ------------- | +| *BirdApi* | [**getBird**](docs/BirdApi.md#getbird) | **GET** v1/bird/{id} | | + + + +## Documentation for Models + + - [org.openapitools.client.models.Animal](docs/Animal.md) + - [org.openapitools.client.models.AnotherAnimal](docs/AnotherAnimal.md) + - [org.openapitools.client.models.Bird](docs/Bird.md) + - [org.openapitools.client.models.Robobird](docs/Robobird.md) + + + +## Documentation for Authorization + +Endpoints do not require authorization. + + + +## Author + +contact@example.org diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/build.gradle b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/build.gradle new file mode 100644 index 000000000000..92471e246ce9 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/build.gradle @@ -0,0 +1,72 @@ +group 'org.openapitools' +version '1.0.0' + +wrapper { + gradleVersion = '8.14.3' + distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" +} + +buildscript { + ext.kotlin_version = '2.2.20' + ext.retrofitVersion = '3.0.0' + ext.spotless_version = "7.2.1" + + repositories { + maven { url "https://repo1.maven.org/maven2" } + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" + classpath "com.diffplug.spotless:spotless-plugin-gradle:$spotless_version" + } +} + +apply plugin: 'kotlin' +apply plugin: 'kotlinx-serialization' +apply plugin: 'maven-publish' +apply plugin: 'com.diffplug.spotless' + +repositories { + maven { url "https://repo1.maven.org/maven2" } +} + +// Use spotless plugin to automatically format code, remove unused import, etc +// To apply changes directly to the file, run `gradlew spotlessApply` +// Ref: https://github.com/diffplug/spotless/tree/main/plugin-gradle +spotless { + // comment out below to run spotless as part of the `check` task + enforceCheck false + + format 'misc', { + // define the files (e.g. '*.gradle', '*.md') to apply `misc` to + target '.gitignore' + + // define the steps to apply to those files + trimTrailingWhitespace() + indentWithSpaces() // Takes an integer argument if you don't like 4 + endWithNewline() + } + kotlin { + ktfmt() + } +} + +test { + useJUnitPlatform() +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0" + implementation "com.squareup.okhttp3:logging-interceptor:5.1.0" + implementation "com.squareup.retrofit2:retrofit:$retrofitVersion" + implementation "com.squareup.retrofit2:converter-kotlinx-serialization:$retrofitVersion" + implementation "com.squareup.retrofit2:converter-scalars:$retrofitVersion" + testImplementation "io.kotlintest:kotlintest-runner-junit5:3.4.2" +} + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions { + freeCompilerArgs += "-Xopt-in=kotlinx.serialization.ExperimentalSerializationApi" + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/Animal.md b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/Animal.md new file mode 100644 index 000000000000..aaffda15d819 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/Animal.md @@ -0,0 +1,14 @@ + +# Animal + +## Properties +| Name | Type | Description | Notes | +| ------------ | ------------- | ------------- | ------------- | +| **discriminator** | **kotlin.String** | | | +| **anotherDiscriminator** | **kotlin.String** | | | +| **propertyA** | **kotlin.String** | | [optional] | +| **sameNameProperty** | **kotlin.String** | | [optional] | +| **propertyB** | **kotlin.String** | | [optional] | + + + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/AnotherAnimal.md b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/AnotherAnimal.md new file mode 100644 index 000000000000..c5bc8ab96395 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/AnotherAnimal.md @@ -0,0 +1,14 @@ + +# AnotherAnimal + +## Properties +| Name | Type | Description | Notes | +| ------------ | ------------- | ------------- | ------------- | +| **discriminator** | **kotlin.String** | | | +| **anotherDiscriminator** | **kotlin.String** | | | +| **propertyA** | **kotlin.String** | | [optional] | +| **sameNameProperty** | **kotlin.String** | | [optional] | +| **propertyB** | **kotlin.String** | | [optional] | + + + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/Bird.md b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/Bird.md new file mode 100644 index 000000000000..f42f4e951c03 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/Bird.md @@ -0,0 +1,13 @@ + +# Bird + +## Properties +| Name | Type | Description | Notes | +| ------------ | ------------- | ------------- | ------------- | +| **discriminator** | **kotlin.String** | | | +| **anotherDiscriminator** | **kotlin.String** | | | +| **propertyA** | **kotlin.String** | | [optional] | +| **sameNameProperty** | **kotlin.Int** | | [optional] | + + + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/BirdApi.md b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/BirdApi.md new file mode 100644 index 000000000000..ef818666da23 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/BirdApi.md @@ -0,0 +1,44 @@ +# BirdApi + +All URIs are relative to *http://example.org* + +| Method | HTTP request | Description | +| ------------- | ------------- | ------------- | +| [**getBird**](BirdApi.md#getBird) | **GET** v1/bird/{id} | | + + + + + +### Example +```kotlin +// Import classes: +//import org.openapitools.client.* +//import org.openapitools.client.infrastructure.* +//import org.openapitools.client.models.* + +val apiClient = ApiClient() +val webService = apiClient.createWebservice(BirdApi::class.java) +val id : java.util.UUID = 38400000-8cf0-11bd-b23e-10b96e4ef00d // java.util.UUID | + +val result : Animal = webService.getBird(id) +``` + +### Parameters +| Name | Type | Description | Notes | +| ------------- | ------------- | ------------- | ------------- | +| **id** | **java.util.UUID**| | | + +### Return type + +[**Animal**](Animal.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/Robobird.md b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/Robobird.md new file mode 100644 index 000000000000..8208e46652a2 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/docs/Robobird.md @@ -0,0 +1,13 @@ + +# Robobird + +## Properties +| Name | Type | Description | Notes | +| ------------ | ------------- | ------------- | ------------- | +| **discriminator** | **kotlin.String** | | | +| **anotherDiscriminator** | **kotlin.String** | | | +| **propertyB** | **kotlin.String** | | [optional] | +| **sameNameProperty** | **kotlin.String** | | [optional] | + + + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradle/wrapper/gradle-wrapper.jar b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000000..2c3521197d7c Binary files /dev/null and b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradle/wrapper/gradle-wrapper.jar differ diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradle/wrapper/gradle-wrapper.properties b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..7705927e949f --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradlew b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradlew new file mode 100644 index 000000000000..51eb8bb47109 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while +APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path +[ -h "$app_path" ] +do +ls=$( ls -ld "$app_path" ) +link=${ls#*' -> '} +case $link in #( +/*) app_path=$link ;; #( +*) app_path=$APP_HOME$link ;; +esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { +echo "$*" +} >&2 + +die () { +echo +echo "$*" +echo +exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( +CYGWIN* ) cygwin=true ;; #( +Darwin* ) darwin=true ;; #( +MSYS* | MINGW* ) msys=true ;; #( +NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then +if [ -x "$JAVA_HOME/jre/sh/java" ] ; then +# IBM's JDK on AIX uses strange locations for the executables +JAVACMD=$JAVA_HOME/jre/sh/java +else +JAVACMD=$JAVA_HOME/bin/java +fi +if [ ! -x "$JAVACMD" ] ; then +die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi +else +JAVACMD=java +if ! command -v java >/dev/null 2>&1 +then +die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then +case $MAX_FD in #( +max*) +# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. +# shellcheck disable=SC2039,SC3045 +MAX_FD=$( ulimit -H -n ) || +warn "Could not query maximum file descriptor limit" +esac +case $MAX_FD in #( +'' | soft) :;; #( +*) +# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. +# shellcheck disable=SC2039,SC3045 +ulimit -n "$MAX_FD" || +warn "Could not set maximum file descriptor limit to $MAX_FD" +esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then +APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) +CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + +JAVACMD=$( cygpath --unix "$JAVACMD" ) + +# Now convert the arguments - kludge to limit ourselves to /bin/sh +for arg do +if +case $arg in #( +-*) false ;; # don't mess with options #( +/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath +[ -e "$t" ] ;; #( +*) false ;; +esac +then +arg=$( cygpath --path --ignore --mixed "$arg" ) +fi +# Roll the args list around exactly as many times as the number of +# args, so each arg winds up back in the position where it started, but +# possibly modified. +# +# NB: a `for` loop captures its iteration list before it begins, so +# changing the positional parameters here affects neither the number of +# iterations, nor the values presented in `arg`. +shift # remove old arg +set -- "$@" "$arg" # push replacement arg +done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ +"-Dorg.gradle.appname=$APP_BASE_NAME" \ +-classpath "$CLASSPATH" \ +org.gradle.wrapper.GradleWrapperMain \ +"$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then +die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( +printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | +xargs -n1 | +sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | +tr '\n' ' ' +)" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradlew.bat b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradlew.bat new file mode 100644 index 000000000000..9d21a21834d5 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/proguard-rules.pro b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/proguard-rules.pro new file mode 100644 index 000000000000..7c7b08bf3810 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/proguard-rules.pro @@ -0,0 +1,11 @@ +-keepattributes *Annotation*, InnerClasses +-dontnote kotlinx.serialization.AnnotationsKt # core serialization annotations + +# kotlinx-serialization-json specific. Add this if you have java.lang.NoClassDefFoundError kotlinx.serialization.json.JsonObjectSerializer +-keepclassmembers class kotlinx.serialization.json.** { *** Companion; } +-keepclasseswithmembers class kotlinx.serialization.json.** { kotlinx.serialization.KSerializer serializer(...); } + +# project specific. +-keep,includedescriptorclasses class org.openapitools.client.models.**$$serializer { *; } +-keepclassmembers class org.openapitools.client.models.** { *** Companion; } +-keepclasseswithmembers class org.openapitools.client.models.** { kotlinx.serialization.KSerializer serializer(...); } diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/settings.gradle b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/settings.gradle new file mode 100644 index 000000000000..bdd710c62b9b --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'kotlin-oneOf-discriminator' diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/apis/BirdApi.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/apis/BirdApi.kt new file mode 100644 index 000000000000..409897ab75da --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/apis/BirdApi.kt @@ -0,0 +1,26 @@ +package org.openapitools.client.apis + +import org.openapitools.client.infrastructure.CollectionFormats.* +import retrofit2.http.* +import retrofit2.Call +import okhttp3.RequestBody +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import org.openapitools.client.models.Animal + +interface BirdApi { + /** + * GET v1/bird/{id} + * + * + * Responses: + * - 200: OK + * + * @param id + * @return [Call]<[Animal]> + */ + @GET("v1/bird/{id}") + fun getBird(@Path("id") id: java.util.UUID): Call + +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt new file mode 100644 index 000000000000..556870f29311 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -0,0 +1,111 @@ +package org.openapitools.client.infrastructure + + +import okhttp3.Call +import okhttp3.Interceptor +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Converter +import retrofit2.CallAdapter +import retrofit2.converter.scalars.ScalarsConverterFactory + +import retrofit2.converter.kotlinx.serialization.asConverterFactory +import org.openapitools.client.infrastructure.Serializer.kotlinxSerializationJson +import okhttp3.MediaType.Companion.toMediaType + +class ApiClient( + private var baseUrl: String = defaultBasePath, + private val okHttpClientBuilder: OkHttpClient.Builder? = null, + private val callFactory: Call.Factory? = null, + private val callAdapterFactories: List = listOf( + ), + private val converterFactories: List = listOf( + ScalarsConverterFactory.create(), + kotlinxSerializationJson.asConverterFactory("application/json".toMediaType()), + ) +) { + private val apiAuthorizations = mutableMapOf() + var logger: ((String) -> Unit)? = null + + private val retrofitBuilder: Retrofit.Builder by lazy { + Retrofit.Builder() + .baseUrl(baseUrl) + .apply { + callAdapterFactories.forEach { + addCallAdapterFactory(it) + } + } + .apply { + converterFactories.forEach { + addConverterFactory(it) + } + } + } + + private val clientBuilder: OkHttpClient.Builder by lazy { + okHttpClientBuilder ?: defaultClientBuilder + } + + private val defaultClientBuilder: OkHttpClient.Builder by lazy { + OkHttpClient() + .newBuilder() + .addInterceptor(HttpLoggingInterceptor { message -> logger?.invoke(message) } + .apply { level = HttpLoggingInterceptor.Level.BODY } + ) + } + + init { + normalizeBaseUrl() + } + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Authorization interceptor + * @return ApiClient + */ + fun addAuthorization(authName: String, authorization: Interceptor): ApiClient { + if (apiAuthorizations.containsKey(authName)) { + throw RuntimeException("auth name $authName already in api authorizations") + } + apiAuthorizations[authName] = authorization + clientBuilder.addInterceptor(authorization) + return this + } + + fun setLogger(logger: (String) -> Unit): ApiClient { + this.logger = logger + return this + } + + fun createService(serviceClass: Class): S { + val usedCallFactory = this.callFactory ?: clientBuilder.build() + return retrofitBuilder.callFactory(usedCallFactory).build().create(serviceClass) + } + + private fun normalizeBaseUrl() { + if (!baseUrl.endsWith("/")) { + baseUrl += "/" + } + } + + private inline fun Iterable.runOnFirst(callback: U.() -> Unit) { + for (element in this) { + if (element is U) { + callback.invoke(element) + break + } + } + } + + companion object { + @JvmStatic + protected val baseUrlKey: String = "org.openapitools.client.baseUrl" + + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(baseUrlKey, "http://example.org") + } + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt new file mode 100644 index 000000000000..0c0d0d00fcfa --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt @@ -0,0 +1,19 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicBoolean + +object AtomicBooleanAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicBoolean) { + encoder.encodeBoolean(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicBoolean = AtomicBoolean(decoder.decodeBoolean()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicBoolean", PrimitiveKind.BOOLEAN) +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt new file mode 100644 index 000000000000..0060b2a0f1c3 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt @@ -0,0 +1,19 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicInteger + +object AtomicIntegerAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicInteger) { + encoder.encodeInt(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicInteger = AtomicInteger(decoder.decodeInt()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicInteger", PrimitiveKind.INT) +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt new file mode 100644 index 000000000000..6de80cc56bd5 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt @@ -0,0 +1,19 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicLong + +object AtomicLongAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicLong) { + encoder.encodeLong(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicLong = AtomicLong(decoder.decodeLong()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicLong", PrimitiveKind.LONG) +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt new file mode 100644 index 000000000000..86cb9efdd727 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt @@ -0,0 +1,15 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.math.BigDecimal + +object BigDecimalAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING) + override fun deserialize(decoder: Decoder): BigDecimal = BigDecimal(decoder.decodeString()) + override fun serialize(encoder: Encoder, value: BigDecimal) = encoder.encodeString(value.toPlainString()) +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt new file mode 100644 index 000000000000..136017cb21bc --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt @@ -0,0 +1,20 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.math.BigInteger + +object BigIntegerAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigInteger", PrimitiveKind.STRING) + override fun deserialize(decoder: Decoder): BigInteger { + return BigInteger(decoder.decodeString()) + } + + override fun serialize(encoder: Encoder, value: BigInteger) { + encoder.encodeString(value.toString()) + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/CollectionFormats.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/CollectionFormats.kt new file mode 100644 index 000000000000..7f404da69ea0 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/CollectionFormats.kt @@ -0,0 +1,56 @@ +package org.openapitools.client.infrastructure + +class CollectionFormats { + + open class CSVParams { + + var params: List + + constructor(params: List) { + this.params = params + } + + constructor(vararg params: String) { + this.params = listOf(*params) + } + + override fun toString(): String { + return params.joinToString(",") + } + } + + open class SSVParams : CSVParams { + + constructor(params: List) : super(params) + + constructor(vararg params: String) : super(*params) + + override fun toString(): String { + return params.joinToString(" ") + } + } + + class TSVParams : CSVParams { + + constructor(params: List) : super(params) + + constructor(vararg params: String) : super(*params) + + override fun toString(): String { + return params.joinToString("\t") + } + } + + class PIPESParams : CSVParams { + + constructor(params: List) : super(params) + + constructor(vararg params: String) : super(*params) + + override fun toString(): String { + return params.joinToString("|") + } + } + + class SPACEParams : SSVParams() +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt new file mode 100644 index 000000000000..923828ff017b --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt @@ -0,0 +1,22 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.time.LocalDate +import java.time.format.DateTimeFormatter + +object LocalDateAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: LocalDate) { + encoder.encodeString(DateTimeFormatter.ISO_LOCAL_DATE.format(value)) + } + + override fun deserialize(decoder: Decoder): LocalDate { + return LocalDate.parse(decoder.decodeString(), DateTimeFormatter.ISO_LOCAL_DATE) + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt new file mode 100644 index 000000000000..52d73dc0ad03 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt @@ -0,0 +1,22 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +object LocalDateTimeAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: LocalDateTime) { + encoder.encodeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value)) + } + + override fun deserialize(decoder: Decoder): LocalDateTime { + return LocalDateTime.parse(decoder.decodeString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME) + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt new file mode 100644 index 000000000000..f098b5ed1e15 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt @@ -0,0 +1,22 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter + +object OffsetDateTimeAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("OffsetDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: OffsetDateTime) { + encoder.encodeString(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value)) + } + + override fun deserialize(decoder: Decoder): OffsetDateTime { + return OffsetDateTime.parse(decoder.decodeString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME) + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExt.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExt.kt new file mode 100644 index 000000000000..0f121a95f5be --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExt.kt @@ -0,0 +1,4 @@ +package org.openapitools.client.infrastructure + +import retrofit2.Response + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt new file mode 100644 index 000000000000..1bed97472b3a --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt @@ -0,0 +1,73 @@ +package org.openapitools.client.infrastructure + +import java.math.BigDecimal +import java.math.BigInteger +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.util.UUID +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonBuilder +import kotlinx.serialization.modules.SerializersModule +import kotlinx.serialization.modules.SerializersModuleBuilder +import java.net.URI +import java.net.URL +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.atomic.AtomicLong + +object Serializer { + private var isAdaptersInitialized = false + + @JvmStatic + val kotlinxSerializationAdapters: SerializersModule by lazy { + isAdaptersInitialized = true + SerializersModule { + contextual(BigDecimal::class, BigDecimalAdapter) + contextual(BigInteger::class, BigIntegerAdapter) + contextual(LocalDate::class, LocalDateAdapter) + contextual(LocalDateTime::class, LocalDateTimeAdapter) + contextual(OffsetDateTime::class, OffsetDateTimeAdapter) + contextual(UUID::class, UUIDAdapter) + contextual(AtomicInteger::class, AtomicIntegerAdapter) + contextual(AtomicLong::class, AtomicLongAdapter) + contextual(AtomicBoolean::class, AtomicBooleanAdapter) + contextual(URI::class, URIAdapter) + contextual(URL::class, URLAdapter) + contextual(StringBuilder::class, StringBuilderAdapter) + + apply(kotlinxSerializationAdaptersConfiguration) + } + } + + var kotlinxSerializationAdaptersConfiguration: SerializersModuleBuilder.() -> Unit = {} + set(value) { + check(!isAdaptersInitialized) { + "Cannot configure kotlinxSerializationAdaptersConfiguration after kotlinxSerializationAdapters has been initialized." + } + field = value + } + + private var isJsonInitialized = false + + @JvmStatic + val kotlinxSerializationJson: Json by lazy { + isJsonInitialized = true + Json { + serializersModule = kotlinxSerializationAdapters + encodeDefaults = true + ignoreUnknownKeys = true + isLenient = true + + apply(kotlinxSerializationJsonConfiguration) + } + } + + var kotlinxSerializationJsonConfiguration: JsonBuilder.() -> Unit = {} + set(value) { + check(!isJsonInitialized) { + "Cannot configure kotlinxSerializationJsonConfiguration after kotlinxSerializationJson has been initialized." + } + field = value + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt new file mode 100644 index 000000000000..b510e73808a5 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt @@ -0,0 +1,18 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor + +object StringBuilderAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: StringBuilder) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): StringBuilder = StringBuilder(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("StringBuilder", PrimitiveKind.STRING) +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt new file mode 100644 index 000000000000..8b4015feddc6 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt @@ -0,0 +1,19 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.net.URI + +object URIAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: URI) { + encoder.encodeString(value.toASCIIString()) + } + + override fun deserialize(decoder: Decoder): URI = URI(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("URI", PrimitiveKind.STRING) +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt new file mode 100644 index 000000000000..9aa0326662e7 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt @@ -0,0 +1,19 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.net.URL + +object URLAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: URL) { + encoder.encodeString(value.toExternalForm()) + } + + override fun deserialize(decoder: Decoder): URL = URL(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("URL", PrimitiveKind.STRING) +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt new file mode 100644 index 000000000000..64ff2f9139fe --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt @@ -0,0 +1,21 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.UUID + +object UUIDAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: UUID) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): UUID { + return UUID.fromString(decoder.decodeString()) + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/Animal.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/Animal.kt new file mode 100644 index 000000000000..5daa221dc730 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/Animal.kt @@ -0,0 +1,93 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import org.openapitools.client.models.Bird +import org.openapitools.client.models.Robobird + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.SerializationException +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.json.JsonDecoder +import kotlinx.serialization.json.JsonEncoder +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive + +/** + * + * + */ +@Serializable(with = AnimalSerializer::class) +sealed interface Animal { + @JvmInline + value class BirdWrapper(val value: Bird) : Animal + + @JvmInline + value class RobobirdWrapper(val value: Robobird) : Animal + +} + +object AnimalSerializer : KSerializer { + override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Animal") + + override fun serialize(encoder: Encoder, value: Animal) { + require(encoder is JsonEncoder) + val jsonObject = when (value) { + is Animal.BirdWrapper -> { + val jsonMap = encoder.json.encodeToJsonElement(Bird.serializer(), value.value).jsonObject.toMutableMap() + jsonMap["discriminator"] = JsonPrimitive("BIRD") + JsonObject(jsonMap) + } + is Animal.RobobirdWrapper -> { + val jsonMap = encoder.json.encodeToJsonElement(Robobird.serializer(), value.value).jsonObject.toMutableMap() + jsonMap["discriminator"] = JsonPrimitive("ROBOBIRD") + JsonObject(jsonMap) + } + } + encoder.encodeJsonElement(jsonObject) + } + + override fun deserialize(decoder: Decoder): Animal { + require(decoder is JsonDecoder) + val element = decoder.decodeJsonElement().jsonObject + + val discriminatorValue = element["discriminator"]?.jsonPrimitive?.content + ?: throw SerializationException("Missing discriminator field") + + return when (discriminatorValue) { + "BIRD" -> { + val decoded = decoder.json.decodeFromJsonElement(Bird.serializer(), element) + Animal.BirdWrapper(decoded) + } + "ROBOBIRD" -> { + val decoded = decoder.json.decodeFromJsonElement(Robobird.serializer(), element) + Animal.RobobirdWrapper(decoded) + } + else -> throw SerializationException("Unknown Animal discriminator: $discriminatorValue") + } + } +} + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/AnotherAnimal.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/AnotherAnimal.kt new file mode 100644 index 000000000000..4fa0bb4eb937 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/AnotherAnimal.kt @@ -0,0 +1,93 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import org.openapitools.client.models.Bird +import org.openapitools.client.models.Robobird + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.SerializationException +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.json.JsonDecoder +import kotlinx.serialization.json.JsonEncoder +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive + +/** + * + * + */ +@Serializable(with = AnotherAnimalSerializer::class) +sealed interface AnotherAnimal { + @JvmInline + value class AnotherBirdWrapper(val value: Bird) : AnotherAnimal + + @JvmInline + value class AnotherRobobirdWrapper(val value: Robobird) : AnotherAnimal + +} + +object AnotherAnimalSerializer : KSerializer { + override val descriptor: SerialDescriptor = buildClassSerialDescriptor("AnotherAnimal") + + override fun serialize(encoder: Encoder, value: AnotherAnimal) { + require(encoder is JsonEncoder) + val jsonObject = when (value) { + is AnotherAnimal.AnotherBirdWrapper -> { + val jsonMap = encoder.json.encodeToJsonElement(Bird.serializer(), value.value).jsonObject.toMutableMap() + jsonMap["another_discriminator"] = JsonPrimitive("ANOTHER_BIRD") + JsonObject(jsonMap) + } + is AnotherAnimal.AnotherRobobirdWrapper -> { + val jsonMap = encoder.json.encodeToJsonElement(Robobird.serializer(), value.value).jsonObject.toMutableMap() + jsonMap["another_discriminator"] = JsonPrimitive("ANOTHER_ROBOBIRD") + JsonObject(jsonMap) + } + } + encoder.encodeJsonElement(jsonObject) + } + + override fun deserialize(decoder: Decoder): AnotherAnimal { + require(decoder is JsonDecoder) + val element = decoder.decodeJsonElement().jsonObject + + val discriminatorValue = element["another_discriminator"]?.jsonPrimitive?.content + ?: throw SerializationException("Missing another_discriminator field") + + return when (discriminatorValue) { + "ANOTHER_BIRD" -> { + val decoded = decoder.json.decodeFromJsonElement(Bird.serializer(), element) + AnotherAnimal.AnotherBirdWrapper(decoded) + } + "ANOTHER_ROBOBIRD" -> { + val decoded = decoder.json.decodeFromJsonElement(Robobird.serializer(), element) + AnotherAnimal.AnotherRobobirdWrapper(decoded) + } + else -> throw SerializationException("Unknown AnotherAnimal another_discriminator: $discriminatorValue") + } + } +} + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/Bird.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/Bird.kt new file mode 100644 index 000000000000..f74aff360a72 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/Bird.kt @@ -0,0 +1,56 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +/** + * + * + * @param discriminator + * @param anotherDiscriminator + * @param propertyA + * @param sameNameProperty + */ +@Serializable + +data class Bird ( + + @SerialName(value = "discriminator") + val discriminator: kotlin.String, + + @SerialName(value = "another_discriminator") + val anotherDiscriminator: kotlin.String, + + @SerialName(value = "propertyA") + val propertyA: kotlin.String? = null, + + @SerialName(value = "sameNameProperty") + val sameNameProperty: kotlin.Int? = null + +) { + + +} + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/Robobird.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/Robobird.kt new file mode 100644 index 000000000000..7af01c66bb1a --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/main/kotlin/org/openapitools/client/models/Robobird.kt @@ -0,0 +1,56 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +/** + * + * + * @param discriminator + * @param anotherDiscriminator + * @param propertyB + * @param sameNameProperty + */ +@Serializable + +data class Robobird ( + + @SerialName(value = "discriminator") + val discriminator: kotlin.String, + + @SerialName(value = "another_discriminator") + val anotherDiscriminator: kotlin.String, + + @SerialName(value = "propertyB") + val propertyB: kotlin.String? = null, + + @SerialName(value = "sameNameProperty") + val sameNameProperty: kotlin.String? = null + +) { + + +} + diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/apis/BirdApiTest.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/apis/BirdApiTest.kt new file mode 100644 index 000000000000..8b6855ead2f1 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/apis/BirdApiTest.kt @@ -0,0 +1,38 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.apis + +import io.kotlintest.shouldBe +import io.kotlintest.specs.ShouldSpec + +import org.openapitools.client.apis.BirdApi +import org.openapitools.client.models.Animal + +class BirdApiTest : ShouldSpec() { + init { + // uncomment below to create an instance of BirdApi + //val apiInstance = BirdApi() + + // to test getBird + should("test getBird") { + // uncomment below to test getBird + //val id : java.util.UUID = 38400000-8cf0-11bd-b23e-10b96e4ef00d // java.util.UUID | + //val result : Animal = apiInstance.getBird(id) + //result shouldBe ("TODO") + } + + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/AnimalTest.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/AnimalTest.kt new file mode 100644 index 000000000000..18101a635bd3 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/AnimalTest.kt @@ -0,0 +1,61 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import io.kotlintest.shouldBe +import io.kotlintest.specs.ShouldSpec + +import org.openapitools.client.models.Animal +import org.openapitools.client.models.Bird +import org.openapitools.client.models.Robobird + +class AnimalTest : ShouldSpec() { + init { + // uncomment below to create an instance of Animal + //val modelInstance = Animal() + + // to test the property `discriminator` + should("test discriminator") { + // uncomment below to test the property + //modelInstance.discriminator shouldBe ("TODO") + } + + // to test the property `anotherDiscriminator` + should("test anotherDiscriminator") { + // uncomment below to test the property + //modelInstance.anotherDiscriminator shouldBe ("TODO") + } + + // to test the property `propertyA` + should("test propertyA") { + // uncomment below to test the property + //modelInstance.propertyA shouldBe ("TODO") + } + + // to test the property `sameNameProperty` + should("test sameNameProperty") { + // uncomment below to test the property + //modelInstance.sameNameProperty shouldBe ("TODO") + } + + // to test the property `propertyB` + should("test propertyB") { + // uncomment below to test the property + //modelInstance.propertyB shouldBe ("TODO") + } + + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/AnotherAnimalTest.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/AnotherAnimalTest.kt new file mode 100644 index 000000000000..113939b033f9 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/AnotherAnimalTest.kt @@ -0,0 +1,61 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import io.kotlintest.shouldBe +import io.kotlintest.specs.ShouldSpec + +import org.openapitools.client.models.AnotherAnimal +import org.openapitools.client.models.Bird +import org.openapitools.client.models.Robobird + +class AnotherAnimalTest : ShouldSpec() { + init { + // uncomment below to create an instance of AnotherAnimal + //val modelInstance = AnotherAnimal() + + // to test the property `discriminator` + should("test discriminator") { + // uncomment below to test the property + //modelInstance.discriminator shouldBe ("TODO") + } + + // to test the property `anotherDiscriminator` + should("test anotherDiscriminator") { + // uncomment below to test the property + //modelInstance.anotherDiscriminator shouldBe ("TODO") + } + + // to test the property `propertyA` + should("test propertyA") { + // uncomment below to test the property + //modelInstance.propertyA shouldBe ("TODO") + } + + // to test the property `sameNameProperty` + should("test sameNameProperty") { + // uncomment below to test the property + //modelInstance.sameNameProperty shouldBe ("TODO") + } + + // to test the property `propertyB` + should("test propertyB") { + // uncomment below to test the property + //modelInstance.propertyB shouldBe ("TODO") + } + + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/BirdTest.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/BirdTest.kt new file mode 100644 index 000000000000..3194f395a3f5 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/BirdTest.kt @@ -0,0 +1,53 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import io.kotlintest.shouldBe +import io.kotlintest.specs.ShouldSpec + +import org.openapitools.client.models.Bird + +class BirdTest : ShouldSpec() { + init { + // uncomment below to create an instance of Bird + //val modelInstance = Bird() + + // to test the property `discriminator` + should("test discriminator") { + // uncomment below to test the property + //modelInstance.discriminator shouldBe ("TODO") + } + + // to test the property `anotherDiscriminator` + should("test anotherDiscriminator") { + // uncomment below to test the property + //modelInstance.anotherDiscriminator shouldBe ("TODO") + } + + // to test the property `propertyA` + should("test propertyA") { + // uncomment below to test the property + //modelInstance.propertyA shouldBe ("TODO") + } + + // to test the property `sameNameProperty` + should("test sameNameProperty") { + // uncomment below to test the property + //modelInstance.sameNameProperty shouldBe ("TODO") + } + + } +} diff --git a/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/RobobirdTest.kt b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/RobobirdTest.kt new file mode 100644 index 000000000000..5b4962571242 --- /dev/null +++ b/samples/client/others/kotlin-oneOf-discriminator-kotlinx-serialization/src/test/kotlin/org/openapitools/client/models/RobobirdTest.kt @@ -0,0 +1,53 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import io.kotlintest.shouldBe +import io.kotlintest.specs.ShouldSpec + +import org.openapitools.client.models.Robobird + +class RobobirdTest : ShouldSpec() { + init { + // uncomment below to create an instance of Robobird + //val modelInstance = Robobird() + + // to test the property `discriminator` + should("test discriminator") { + // uncomment below to test the property + //modelInstance.discriminator shouldBe ("TODO") + } + + // to test the property `anotherDiscriminator` + should("test anotherDiscriminator") { + // uncomment below to test the property + //modelInstance.anotherDiscriminator shouldBe ("TODO") + } + + // to test the property `propertyB` + should("test propertyB") { + // uncomment below to test the property + //modelInstance.propertyB shouldBe ("TODO") + } + + // to test the property `sameNameProperty` + should("test sameNameProperty") { + // uncomment below to test the property + //modelInstance.sameNameProperty shouldBe ("TODO") + } + + } +} diff --git a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPet.kt b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPet.kt index 5922d1746556..d3088adf3dda 100644 --- a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPet.kt +++ b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPet.kt @@ -35,8 +35,6 @@ import java.io.IOException * * */ - - data class ApiUserOrPet(var actualInstance: Any? = null) { class CustomTypeAdapterFactory : TypeAdapterFactory { @@ -155,3 +153,4 @@ data class ApiUserOrPet(var actualInstance: Any? = null) { } } } + diff --git a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPetOrArrayString.kt b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPetOrArrayString.kt index 02d127bb854a..44eaa6093e8b 100644 --- a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPetOrArrayString.kt +++ b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPetOrArrayString.kt @@ -35,8 +35,6 @@ import java.io.IOException * * */ - - data class ApiUserOrPetOrArrayString(var actualInstance: Any? = null) { class CustomTypeAdapterFactory : TypeAdapterFactory { @@ -205,3 +203,4 @@ data class ApiUserOrPetOrArrayString(var actualInstance: Any? = null) { } } } +