Skip to content

Commit 2cdd9ae

Browse files
authored
Kotlin Multiplatform polymorphism with custom discriminator support (#21772)
* Enable descriminator for kotlin-client multiplatform * update template * add sample * update samples-kotlin-client workflow * add missing JsonClassDiscriminator import * fix gradlew permission * update sample * fix sample * re-generate sample
1 parent 443fd76 commit 2cdd9ae

File tree

39 files changed

+1461
-6
lines changed

39 files changed

+1461
-6
lines changed

.github/workflows/samples-kotlin-client.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
- samples/client/petstore/kotlin-moshi-codegen
3434
- samples/client/petstore/kotlin-multiplatform
3535
- samples/client/petstore/kotlin-multiplatform-kotlinx-datetime
36+
- samples/client/petstore/kotlin-multiplatform-allOf-discriminator
3637
- samples/client/petstore/kotlin-nonpublic
3738
- samples/client/petstore/kotlin-nullable
3839
- samples/client/petstore/kotlin-retrofit2
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
generatorName: kotlin
2+
outputDir: samples/client/petstore/kotlin-multiplatform-allOf-discriminator
3+
library: multiplatform
4+
dateLibrary: kotlinx-datetime
5+
inputSpec: modules/openapi-generator/src/test/resources/3_0/kotlin/polymorphism.yaml
6+
templateDir: modules/openapi-generator/src/main/resources/kotlin-client
7+
additionalProperties:
8+
artifactId: kotlin-multiplatform-allOf-discriminator

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ public ModelsMap postProcessModels(ModelsMap objs) {
966966
@Override
967967
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
968968
objs = super.postProcessAllModels(objs);
969-
if (getSerializationLibrary() == SERIALIZATION_LIBRARY_TYPE.kotlinx_serialization) {
969+
if (getSerializationLibrary() == SERIALIZATION_LIBRARY_TYPE.kotlinx_serialization || getLibrary().equals(MULTIPLATFORM)) {
970970
// The loop removes unneeded variables so commas are handled correctly in the related templates
971971
for (Map.Entry<String, ModelsMap> modelsMap : objs.entrySet()) {
972972
for (ModelMap mo : modelsMap.getValue().getModels()) {

modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ import kotlinx.parcelize.Parcelize
5555
import kotlinx.serialization.*
5656
import kotlinx.serialization.descriptors.*
5757
import kotlinx.serialization.encoding.*
58+
{{#discriminator}}
59+
import kotlinx.serialization.json.JsonClassDiscriminator
60+
{{/discriminator}}
5861
{{/multiplatform}}
5962
{{#serializableModel}}
6063
import java.io.Serializable
@@ -74,7 +77,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
7477
{{#parcelizeModels}}
7578
@Parcelize
7679
{{/parcelizeModels}}
77-
{{#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}}
80+
{{#multiplatform}}@Serializable{{/multiplatform}}{{#kotlinx_serialization}}{{#serializableModel}}@KSerializable{{/serializableModel}}{{^serializableModel}}@Serializable{{/serializableModel}}{{/kotlinx_serialization}}{{#moshi}}{{#moshiCodeGen}}@JsonClass(generateAdapter = true){{/moshiCodeGen}}{{/moshi}}{{#jackson}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{/jackson}}
7881
{{#isDeprecated}}
7982
@Deprecated(message = "This schema is deprecated.")
8083
{{/isDeprecated}}
@@ -91,13 +94,21 @@ import {{packageName}}.infrastructure.ITransformForStorage
9194
@SerialName(value = {{#lambda.doublequote}}{{{additionalProperties.discriminatorValue}}}{{/lambda.doublequote}})
9295
{{/additionalProperties.discriminatorValue}}
9396
{{/kotlinx_serialization}}
94-
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}{{#discriminator}}{{#kotlinx_serialization}}sealed class{{/kotlinx_serialization}}{{^kotlinx_serialization}}interface{{/kotlinx_serialization}}{{/discriminator}}{{^discriminator}}{{#hasVars}}data {{/hasVars}}class{{/discriminator}} {{classname}}{{^discriminator}} (
97+
{{#multiplatform}}{{#discriminator}}
98+
@OptIn(ExperimentalSerializationApi::class)
99+
@JsonClassDiscriminator(discriminator = "{{{discriminator.propertyName}}}")
100+
{{/discriminator}}
101+
{{#additionalProperties.discriminatorValue}}
102+
@SerialName(value = {{#lambda.doublequote}}{{{additionalProperties.discriminatorValue}}}{{/lambda.doublequote}})
103+
{{/additionalProperties.discriminatorValue}}
104+
{{/multiplatform}}
105+
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}{{#discriminator}}{{#kotlinx_serialization}}sealed class{{/kotlinx_serialization}}{{#multiplatform}}sealed class{{/multiplatform}}{{^multiplatform}}{{^kotlinx_serialization}}interface{{/kotlinx_serialization}}{{/multiplatform}}{{/discriminator}}{{^discriminator}}{{#hasVars}}data {{/hasVars}}class{{/discriminator}} {{classname}}{{^discriminator}} (
95106

96107
{{#allVars}}
97108
{{#required}}{{>data_class_req_var}}{{/required}}{{^required}}{{>data_class_opt_var}}{{/required}}{{^-last}},{{/-last}}
98109

99110
{{/allVars}}
100-
){{/discriminator}}{{#parent}}{{^serializableModel}}{{^parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#kotlinx_serialization}}(){{/kotlinx_serialization}}{{#isArray}}(){{/isArray}}{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{#serializableModel}}{{^parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Serializable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{^serializableModel}}{{#parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{#serializableModel}}{{#parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Serializable, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{#serializableModel}}{{^parcelizeModels}} : Serializable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{^serializableModel}}{{#parcelizeModels}} : Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{#serializableModel}}{{#parcelizeModels}} : Serializable, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#generateRoomModels}}{{#parent}}, {{/parent}}{{^discriminator}}{{^parent}}:{{/parent}} ITransformForStorage<{{classname}}RoomModel>{{/discriminator}}{{/generateRoomModels}}{{#vendorExtensions.x-has-data-class-body}} {
111+
){{/discriminator}}{{#parent}}{{^serializableModel}}{{^parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#kotlinx_serialization}}(){{/kotlinx_serialization}}{{#multiplatform}}(){{/multiplatform}}{{#isArray}}(){{/isArray}}{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{#serializableModel}}{{^parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Serializable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{^serializableModel}}{{#parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{#serializableModel}}{{#parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Serializable, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{#serializableModel}}{{^parcelizeModels}} : Serializable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{^serializableModel}}{{#parcelizeModels}} : Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{#serializableModel}}{{#parcelizeModels}} : Serializable, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#generateRoomModels}}{{#parent}}, {{/parent}}{{^discriminator}}{{^parent}}:{{/parent}} ITransformForStorage<{{classname}}RoomModel>{{/discriminator}}{{/generateRoomModels}}{{#vendorExtensions.x-has-data-class-body}} {
101112
{{/vendorExtensions.x-has-data-class-body}}
102113
{{#generateRoomModels}}
103114
companion object { }

modules/openapi-generator/src/main/resources/kotlin-client/interface_opt_var.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@
1515
{{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
1616
{{/kotlinx_serialization}}
1717
{{/multiplatform}}
18-
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{/multiplatform}}{{#kotlinx_serialization}}abstract {{/kotlinx_serialization}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}?
18+
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") abstract {{/multiplatform}}{{#kotlinx_serialization}}abstract {{/kotlinx_serialization}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}?

modules/openapi-generator/src/main/resources/kotlin-client/interface_req_var.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@
1515
{{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
1616
{{/kotlinx_serialization}}
1717
{{/multiplatform}}
18-
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") @Required {{/multiplatform}}{{#kotlinx_serialization}}abstract {{/kotlinx_serialization}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}
18+
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") @Required abstract {{/multiplatform}}{{#kotlinx_serialization}}abstract {{/kotlinx_serialization}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# OpenAPI Generator Ignore
2+
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
3+
4+
# Use this file to prevent files from being overwritten by the generator.
5+
# The patterns follow closely to .gitignore or .dockerignore.
6+
7+
# As an example, the C# client generator defines ApiClient.cs.
8+
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9+
#ApiClient.cs
10+
11+
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
12+
#foo/*/qux
13+
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14+
15+
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16+
#foo/**/qux
17+
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18+
19+
# You can also negate patterns with an exclamation (!).
20+
# For example, you can ignore all files in a docs folder with the file extension .md:
21+
#docs/*.md
22+
# Then explicitly reverse the ignore rule for a single file:
23+
#!docs/README.md
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
README.md
2+
build.gradle.kts
3+
docs/Animal.md
4+
docs/Bird.md
5+
docs/BirdApi.md
6+
gradle/wrapper/gradle-wrapper.jar
7+
gradle/wrapper/gradle-wrapper.properties
8+
gradlew
9+
gradlew.bat
10+
settings.gradle.kts
11+
src/commonMain/kotlin/org/openapitools/client/apis/BirdApi.kt
12+
src/commonMain/kotlin/org/openapitools/client/auth/ApiKeyAuth.kt
13+
src/commonMain/kotlin/org/openapitools/client/auth/Authentication.kt
14+
src/commonMain/kotlin/org/openapitools/client/auth/HttpBasicAuth.kt
15+
src/commonMain/kotlin/org/openapitools/client/auth/HttpBearerAuth.kt
16+
src/commonMain/kotlin/org/openapitools/client/auth/OAuth.kt
17+
src/commonMain/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt
18+
src/commonMain/kotlin/org/openapitools/client/infrastructure/ApiClient.kt
19+
src/commonMain/kotlin/org/openapitools/client/infrastructure/Base64ByteArray.kt
20+
src/commonMain/kotlin/org/openapitools/client/infrastructure/Bytes.kt
21+
src/commonMain/kotlin/org/openapitools/client/infrastructure/HttpResponse.kt
22+
src/commonMain/kotlin/org/openapitools/client/infrastructure/OctetByteArray.kt
23+
src/commonMain/kotlin/org/openapitools/client/infrastructure/PartConfig.kt
24+
src/commonMain/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt
25+
src/commonMain/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt
26+
src/commonMain/kotlin/org/openapitools/client/models/Animal.kt
27+
src/commonMain/kotlin/org/openapitools/client/models/Bird.kt
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7.16.0-SNAPSHOT
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# org.openapitools.client - Kotlin client library for Example
2+
3+
An example
4+
5+
## Overview
6+
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.
7+
8+
- API version: 0.1
9+
- Package version:
10+
- Generator version: 7.16.0-SNAPSHOT
11+
- Build package: org.openapitools.codegen.languages.KotlinClientCodegen
12+
For more information, please visit [https://example.org](https://example.org)
13+
14+
## Requires
15+
16+
* Kotlin 1.5.10
17+
18+
## Build
19+
20+
```
21+
./gradlew check assemble
22+
```
23+
24+
This runs all tests and packages the library.
25+
26+
## Features/Implementation Notes
27+
28+
* Supports JSON inputs/outputs, File inputs, and Form inputs.
29+
* Supports collection formats for query parameters: csv, tsv, ssv, pipes.
30+
* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions.
31+
32+
33+
<a id="documentation-for-api-endpoints"></a>
34+
## Documentation for API Endpoints
35+
36+
All URIs are relative to *http://example.org*
37+
38+
| Class | Method | HTTP request | Description |
39+
| ------------ | ------------- | ------------- | ------------- |
40+
| *BirdApi* | [**getBird**](docs/BirdApi.md#getbird) | **GET** /v1/bird/{id} | |
41+
42+
43+
<a id="documentation-for-models"></a>
44+
## Documentation for Models
45+
46+
- [org.openapitools.client.models.Animal](docs/Animal.md)
47+
- [org.openapitools.client.models.Bird](docs/Bird.md)
48+
49+
50+
<a id="documentation-for-authorization"></a>
51+
## Documentation for Authorization
52+
53+
Endpoints do not require authorization.
54+
55+
56+
57+
## Author
58+
59+

0 commit comments

Comments
 (0)