Skip to content

Commit ae65f53

Browse files
committed
kotlinx serialization fixes
- added new config with kotlinx, discriminator (/w custom name) and kotlinx_serialization - remove discriminator properties from the generator in both base and derived classes - set discriminatorValue in additionalProperties of derived classes - add JsonClassDiscriminator the derived classes in the template - set SerialName to discriminatorValue in the template - change base classes to sealed class instead of interface - make variables in base classes abstract
1 parent 3ef45f1 commit ae65f53

File tree

6 files changed

+117
-4
lines changed

6 files changed

+117
-4
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
generatorName: kotlin
2+
outputDir: samples/client/petstore/kotlin-allOff-discriminator-kotlinx-serialization
3+
inputSpec: modules/openapi-generator/src/test/resources/3_0/issue_xxxx.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/kotlin-client
5+
additionalProperties:
6+
artifactId: kotlin-allOff-discriminator
7+
serializableModel: "false"
8+
dateLibrary: java8
9+
enumUnknownDefaultCase: true
10+
serializationLibrary: kotlinx_serialization

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,38 @@ public ModelsMap postProcessModels(ModelsMap objs) {
963963
return objects;
964964
}
965965

966+
@Override
967+
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
968+
objs = super.postProcessAllModels(objs);
969+
if (getSerializationLibrary() == SERIALIZATION_LIBRARY_TYPE.kotlinx_serialization) {
970+
for (Map.Entry<String, ModelsMap> modelsMap : objs.entrySet()) {
971+
for (ModelMap mo : modelsMap.getValue().getModels()) {
972+
CodegenModel cm = mo.getModel();
973+
CodegenDiscriminator discriminator = cm.getDiscriminator();
974+
if (discriminator == null) {
975+
continue;
976+
}
977+
getAllVarProperties(cm).forEach(list -> list.removeIf(var -> var.name == discriminator.getPropertyName()));
978+
979+
for (CodegenDiscriminator.MappedModel mappedModel : discriminator.getMappedModels()) {
980+
CodegenProperty additionalProperties = mappedModel.getModel().getAdditionalProperties();
981+
if (additionalProperties == null) {
982+
additionalProperties = new CodegenProperty();
983+
mappedModel.getModel().setAdditionalProperties(additionalProperties);
984+
}
985+
additionalProperties.discriminatorValue = mappedModel.getMappingName();
986+
getAllVarProperties(mappedModel.getModel()).forEach(list -> list.removeIf(prop -> prop.name == discriminator.getPropertyName()));
987+
}
988+
989+
}
990+
}
991+
}
992+
return objs;
993+
}
994+
private Stream<List<CodegenProperty>> getAllVarProperties(CodegenModel model) {
995+
return Stream.of(model.vars, model.allVars, model.optionalVars, model.requiredVars, model.readOnlyVars, model.readWriteVars);
996+
}
997+
966998
private boolean usesRetrofit2Library() {
967999
return getLibrary() != null && getLibrary().contains(JVM_RETROFIT2);
9681000
}

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ import kotlinx.serialization.encoding.Encoder
4040
{{/enumUnknownDefaultCase}}
4141
{{#hasEnums}}
4242
{{/hasEnums}}
43+
{{#discriminator}}
44+
import kotlinx.serialization.ExperimentalSerializationApi
45+
import kotlinx.serialization.json.JsonClassDiscriminator
46+
{{/discriminator}}
4347
{{/kotlinx_serialization}}
4448
{{#parcelizeModels}}
4549
import android.os.Parcelable
@@ -78,13 +82,21 @@ import {{packageName}}.infrastructure.ITransformForStorage
7882
{{#vendorExtensions.x-class-extra-annotation}}
7983
{{{vendorExtensions.x-class-extra-annotation}}}
8084
{{/vendorExtensions.x-class-extra-annotation}}
81-
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}{{#discriminator}}interface{{/discriminator}}{{^discriminator}}{{#hasVars}}data {{/hasVars}}class{{/discriminator}} {{classname}}{{^discriminator}} (
85+
{{#kotlinx_serialization}}{{#discriminator}}
86+
@OptIn(ExperimentalSerializationApi::class)
87+
@JsonClassDiscriminator(discriminator = "{{{discriminator.propertyName}}}")
88+
{{/discriminator}}
89+
{{#additionalProperties.discriminatorValue}}
90+
@SerialName(value = {{#lambda.doublequote}}{{{additionalProperties.discriminatorValue}}}{{/lambda.doublequote}})
91+
{{/additionalProperties.discriminatorValue}}
92+
{{/kotlinx_serialization}}
93+
{{#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}} (
8294

8395
{{#allVars}}
8496
{{#required}}{{>data_class_req_var}}{{/required}}{{^required}}{{>data_class_opt_var}}{{/required}}{{^-last}},{{/-last}}
8597

8698
{{/allVars}}
87-
){{/discriminator}}{{#parent}}{{^serializableModel}}{{^parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#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}} {
99+
){{/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}} {
88100
{{/vendorExtensions.x-has-data-class-body}}
89101
{{#generateRoomModels}}
90102
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}}{{>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}}}") {{/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}}{{>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 {{/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: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
openapi: 3.0.1
2+
info:
3+
title: Example
4+
description: An example
5+
version: '0.1'
6+
contact:
7+
8+
url: 'https://example.org'
9+
servers:
10+
- url: http://example.org
11+
tags:
12+
- name: bird
13+
paths:
14+
'/v1/bird/{id}':
15+
get:
16+
tags:
17+
- bird
18+
responses:
19+
'200':
20+
description: OK
21+
content:
22+
application/json:
23+
schema:
24+
$ref: '#/components/schemas/bird'
25+
operationId: get-bird
26+
parameters:
27+
- schema:
28+
type: string
29+
format: uuid
30+
name: id
31+
in: path
32+
required: true
33+
components:
34+
schemas:
35+
animal:
36+
title: An animal
37+
type: object
38+
properties:
39+
id:
40+
type: string
41+
format: uuid
42+
optional_property:
43+
type: number
44+
required:
45+
- id
46+
discriminator:
47+
propertyName: discriminator
48+
mapping:
49+
BIRD: '#/components/schemas/bird'
50+
bird:
51+
title: A bird
52+
type: object
53+
allOf:
54+
- $ref: '#/components/schemas/animal'
55+
- properties:
56+
featherType:
57+
type: string
58+
required:
59+
- featherType

0 commit comments

Comments
 (0)