Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Kotlin][client] Support gson and moshi as serialization libraries #3734

Merged
merged 12 commits into from
Aug 29, 2019

Conversation

parachutemind
Copy link
Contributor

@parachutemind parachutemind commented Aug 22, 2019

PR checklist

  • [x ] Read the contribution guidelines.
  • [ - ] Ran the shell script under ./bin/ to update Petstore sample so that CIs can verify the change. (For instance, only need to run ./bin/kotlin-client-petstore.sh, ./bin/openapi3/kotlin-client-petstore.sh if updating the {LANG} (e.g. php, ruby, python, etc) code generator or {LANG} client's mustache templates). Windows batch files can be found in .\bin\windows\. If contributing template-only or documentation-only changes which will change sample output, be sure to build the project first.
  • [ x] Filed the PR against the correct branch: master, 4.1.x, 5.0.x. Default: master.
  • [ x] Copied the technical committee to review the pull request if your PR is targeting a particular programming language. -
    @jimschubert
    @dr4ke616
    @karismann
    @Zomzog

Description of the PR

Summary of changes:

  • Added a new 'serializationEngine' option for config.json with 2 valid values: "moshi" (default) and "gson"
  • updated to kotlin-client mustache templates to support gson's @SerializedName annotation - this also helps with proguard which can break JSON binding to object in release code
  • removed empty {} in the data class body when there is no enums - this fixes annoying visual indicators of empty body in Android Studio IDE when looking at data classes without enums.

Testing:

Test 1

mvn clean install
./bin/kotlin-client-petstore.sh
cd samples/client/petstore/kotlin
gradle wrapper; ./gradlew check assemble test
success

Test 2

./bin/kotlin-client-petstore.sh --additional-properties serializationEngine=gson
cd samples/client/petstore/kotlin
gradle wrapper; ./gradlew check assemble test
success

Test 3

./bin/kotlin-client-petstore.sh --additional-properties serializationEngine=foobar
verified proper error message is displayed:

Exception in thread "main" java.lang.RuntimeException: foobar is an invalid enum property naming option. Please choose from:
  moshi
  gson
	at org.openapitools.codegen.languages.AbstractKotlinCodegen.setSerializationEngine(AbstractKotlinCodegen.java:286)
	at org.openapitools.codegen.languages.AbstractKotlinCodegen.processOpts(AbstractKotlinCodegen.java:360)
	at org.openapitools.codegen.languages.KotlinClientCodegen.processOpts(KotlinClientCodegen.java:122)
	at org.openapitools.codegen.DefaultGenerator.configureGeneratorProperties(DefaultGenerator.java:194)
	at org.openapitools.codegen.DefaultGenerator.generate(DefaultGenerator.java:910)
	at org.openapitools.codegen.cmd.Generate.run(Generate.java:400)
	at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:60)

Test 4

./bin/openapi3/kotlin-client-petstore.sh
cd samples/openapi3/client/petstore/kotlin/
gradle wrapper; ./gradlew check assemble test

Unfortunately, I run into the following error when running the tests above against openapi3. I don't believe this is due to my changes. It seems to be broken in master as well...

> Task :compileKotlin FAILED
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/apis/FakeApi.kt: (338, 114): Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Array<String>?
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/apis/FakeApi.kt: (339, 150): Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Array<String>?
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/apis/FakeApi.kt: (339, 176): Unresolved reference: collectionDelimiter
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumArrays.kt: (44, 1): Expecting a top level declaration
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumArrays.kt: (44, 1): Conflicting overloads: public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumArrays.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file InlineObject2.kt
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumArrays.kt: (44, 1): Function declaration must have a name
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumArrays.kt: (27, 44): Unresolved reference: ArrayEnum
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumArrays.kt: (49, 5): Modifier 'enum' is not applicable to 'local class'
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (74, 1): Expecting a top level declaration
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (74, 1): Conflicting overloads: public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumArrays.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file InlineObject2.kt
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (74, 1): Function declaration must have a name
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (90, 1): Expecting a top level declaration
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (90, 1): Conflicting overloads: public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumArrays.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file InlineObject2.kt
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (90, 1): Function declaration must have a name
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (104, 1): Expecting a top level declaration
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (104, 1): Conflicting overloads: public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumArrays.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file InlineObject2.kt
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (104, 1): Function declaration must have a name
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (34, 38): Unresolved reference: EnumStringRequired
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (40, 31): Unresolved reference: EnumInteger
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (43, 30): Unresolved reference: EnumNumber
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (79, 5): Modifier 'enum' is not applicable to 'local class'
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (95, 5): Modifier 'enum' is not applicable to 'local class'
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (97, 22): The integer literal does not conform to the expected type String
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (99, 22): Type mismatch: inferred type is Int but String was expected
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (109, 5): Modifier 'enum' is not applicable to 'local class'
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (111, 22): The floating-point literal does not conform to the expected type String
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/EnumTest.kt: (113, 22): Type mismatch: inferred type is Double but String was expected
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/InlineObject2.kt: (46, 1): Expecting a top level declaration
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/InlineObject2.kt: (46, 1): Conflicting overloads: public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumArrays.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file EnumTest.kt, public fun <no name provided>(): Unit defined in org.openapitools.client.models in file InlineObject2.kt
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/InlineObject2.kt: (46, 1): Function declaration must have a name
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/InlineObject2.kt: (29, 39): Unresolved reference: EnumFormString
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/InlineObject2.kt: (51, 5): Modifier 'enum' is not applicable to 'local class'
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/MapTest.kt: (45, 37): Type mismatch: inferred type is String but Map<String, String> was expected
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/MapTest.kt: (47, 37): Type mismatch: inferred type is String but Map<String, String> was expected
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/SpecialModelname.kt: (21, 18): An annotation argument must be a compile-time constant
e: .../openapi-generator/samples/openapi3/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/models/SpecialModelname.kt: (21, 20): Unresolved reference: special

Fixes #3414

Summary of changes:
- Added a new 'serializationEngine' option for config.json with 2 valid values: "moshi" (default) and "gson"
- updated to kotlin-client mustache templates to support gson's @SerializedName annotation - this also helps with proguard which can break JSON binding to object in release code
- removed empty {} in the data class body when there is no enums - this fixes annoying visual indicators of empty body in Android Studio IDE when looking at data classes without enums.

Testing:
# Test 1
mvn clean install
./bin/kotlin-client-petstore.sh
cd samples/client/petstore/kotlin
gradle wrapper; ./gradlew check assemble test
success

# Test 2
./bin/kotlin-client-petstore.sh --additional-properties serializationEngine=gson
cd samples/client/petstore/kotlin
gradle wrapper; ./gradlew check assemble test
success

# Test 3
./bin/kotlin-client-petstore.sh --additional-properties serializationEngine=foobar
verified proper error message is displayed:
Exception in thread "main" java.lang.RuntimeException: foobar is an invalid enum property naming option. Please choose from:
  moshi
  gson
	at org.openapitools.codegen.languages.AbstractKotlinCodegen.setSerializationEngine(AbstractKotlinCodegen.java:286)
	at org.openapitools.codegen.languages.AbstractKotlinCodegen.processOpts(AbstractKotlinCodegen.java:360)
	at org.openapitools.codegen.languages.KotlinClientCodegen.processOpts(KotlinClientCodegen.java:122)
	at org.openapitools.codegen.DefaultGenerator.configureGeneratorProperties(DefaultGenerator.java:194)
	at org.openapitools.codegen.DefaultGenerator.generate(DefaultGenerator.java:910)
	at org.openapitools.codegen.cmd.Generate.run(Generate.java:400)
	at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:60)
@parachutemind parachutemind changed the title Fix issue3414 Fix issue3414 [Kotlin][client] Support gson and moshi as serialization engines. Aug 22, 2019
…ngine to serializationLibrary

Fixed the data class mustache template to not add an extra line between the @entity and the variable name
Regenerated petstore samples
@parachutemind
Copy link
Contributor Author

@wing328 any ideas what is going on with ci/circlieci and Travis CI failures.
I'm unable to duplicate those errors in my machine. See details at #3414 (comment)

@jmini
Copy link
Member

jmini commented Aug 27, 2019

in #3759 I have added an new option called serializationLibrary. It think we should try to be consistent with the names.

@jimschubert any opinion?

@parachutemind
Copy link
Contributor Author

parachutemind commented Aug 28, 2019

@jmini I already changed my code to include serializationLibrary based on your PR (wing328 brought the suggestion up). See my last commit 38a8dc2.
The problem I'm facing now is that I'm not sure why travis ci and circleci steps are failing. Seemingly because of javadoc error.. I can't repro locally in my machine.

@wing328 wing328 changed the title Fix issue3414 [Kotlin][client] Support gson and moshi as serialization engines. Fix issue3414 [Kotlin][client] Support gson and moshi as serialization libraries Aug 28, 2019
@wing328 wing328 added this to the 4.1.2 milestone Aug 28, 2019
@wing328 wing328 changed the title Fix issue3414 [Kotlin][client] Support gson and moshi as serialization libraries [Kotlin][client] Support gson and moshi as serialization libraries Aug 28, 2019
@wing328
Copy link
Member

wing328 commented Aug 28, 2019

Unfortunately, I run into the following error when running the tests above against openapi3. I don't believe this is due to my changes. It seems to be broken in master as well...

Let's deal with this issue separately

Copy link
Member

@wing328 wing328 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested both gson and moshi and the result is good.

We can merge this PR once the javadoc warning is fixed.

@@ -202,6 +202,10 @@
public static final String ENUM_PROPERTY_NAMING = "enumPropertyNaming";
public static final String ENUM_PROPERTY_NAMING_DESC = "Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'";

public static final String SERIALIZATION_LIBRARY = "serializationLibrary";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, once merged I will remove org.openapitools.codegen.languages.JavaClientCodegen.SERIALIZATION_LIBRARY and use that instead.

@@ -202,6 +202,10 @@
public static final String ENUM_PROPERTY_NAMING = "enumPropertyNaming";
public static final String ENUM_PROPERTY_NAMING_DESC = "Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'";

public static final String SERIALIZATION_LIBRARY = "serializationLibrary";
public static final String SERIALIZATION_LIBRARY_DESC = "What serialization library to use: 'moshi' (default), or 'gson'";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description is Kotlin specific. Can you move it to Kotlin Codegen?

For instance for java client the choice will be between gson and jackson

Copy link
Contributor Author

@parachutemind parachutemind Aug 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

total brain fart on my part. I got lost in the forest. Commit bfb8701 tries to address this request.

Copy link
Member

@jmini jmini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the Kotlin specific stuff should be kept at Kotlin level and not in CodegenConstants.

@wing328
Copy link
Member

wing328 commented Aug 28, 2019

I think that the Kotlin specific stuff should be kept at Kotlin level and not in CodegenConstants.

We didn't enforce this (from day one) so we can find a lot of generator specified options/constants in CodegenConstants.

I agree we should enforce this by first cleaning it up in the future.

…degen. I picked this layer instead of KotlinClient to make it available to the server in the future. In this commit, I've also updated kotlin.md to document serializationLibrary kotlin options. Testing: re-run mvn clean install and mvn verify
@parachutemind
Copy link
Contributor Author

@wing328 can you re-run ci/circleci and travis-ci checks. I think something got crossed between my merge commit and the actual change.

@wing328
Copy link
Member

wing328 commented Aug 28, 2019

You can close and reopen PR to rerun all tests.

Copy link
Member

@jmini jmini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great contribution. Thank your for updating it.

@jmini jmini merged commit 8f7e43b into OpenAPITools:master Aug 29, 2019
@parachutemind parachutemind deleted the fix_issue3414 branch August 29, 2019 14:53
@wing328
Copy link
Member

wing328 commented Sep 12, 2019

@prisoneroftech thanks for the PR, which has been included in the v4.1.2 release: https://twitter.com/oas_generator/status/1172068944355528705

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[REQ] [Kotlin] Switch between Moshi and Jackson depending on import library
3 participants