OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.44k stars 6.48k forks source link

[REQ] Support for kotlinx.serialization in the Kotlin generator for Kotlin Multiplatform Mobile (KMM) projects #17751

Open NDuering opened 8 months ago

NDuering commented 8 months ago

Is your feature request related to a problem? Please describe.

Yes, currently the OpenAPI Generator does not offer support for kotlinx.serialization library for JSON serialization in its Kotlin generator. For developers working on Kotlin Multiplatform Mobile (KMM) projects, kotlinx.serialization is the recommended library as it provides cross-platform compatibility. However, the current setup in the generator uses libraries not designed for Kotlin/Native, which creates a hurdle for KMM projects.

Describe the solution you'd like

It would be ideal if the OpenAPI Generator could provide an option to generate kotlinx.serialization-compatible code. This could involve an extension of the jsonLibrary option to include "kotlinx" or a similar marker. Model classes would then be annotated with @Serializable, and API clients would utilize kotlinx.serialization JSON parsers to serialize and deserialize payloads.

Describe alternatives you've considered

An alternative could involve manually adapting the code generated by the generator, adding @Serializable annotations and adjusting serialization logic. However, this could become tedious with API changes and is not optimal.

Additional context

With the rising popularity of KMM projects, supporting kotlinx.serialization could help make the OpenAPI Generator more accessible to a broader group of developers. It would be a beneficial extension ensuring the OpenAPI Generator’s timeliness and relevance in the ever-evolving world of Kotlin development.

NDuering commented 8 months ago

!!!! UPDATE !!!! With this configuration: configOptions.set( mapOf( "dateLibrary" to "string", "generateApiTests" to "false", "generateModelTests" to "false", "skipOperationModel" to "true", "overwrite" to "true", "skipValidateSpec" to "true", "library" to "multiplatform", ) )

It was possible to generate an API for KMM, but, unfortunately, the generated code is not operational because the folder for the source code does not lie in the 'src/kotlin/main' folder but is instead in the 'src/kotlin/commonMain'. Therefore, further manual adjustments are needed.

charlee-dev commented 7 months ago

Here is the config i use:

kotlin {
    sourceSets {
        commonMain {
            dependencies {
                ...
            }
        }
        all {
            kotlin.srcDir("build/generate-resources/main/src/$name/kotlin")
        }
    }
}

openApiGenerate {
    generatorName = "kotlin"
    packageName = group.toString()
    inputSpec = "${projectDir.path}/openapi.yml"
    typeMappings.put("string+date-time", "Instant")
    importMappings.put("Instant", "kotlinx.datetime.Instant")
    additionalProperties.set(
        mapOf(
            "library" to "multiplatform",
            "dateLibrary" to "kotlinx-datetime",
            "enumPropertyNaming" to "UPPERCASE",
            "useCoroutines" to "true",
            "generateApiTests" to "false",
            "generateModelTests" to "false",
            "skipOperationModel" to "true",
            "overwrite" to "true",
        )
    )
}

I noticed, if i use additionalProperties.set(...) then it generates all sourceSets correctly with commonMain too.

CleanShot 2024-02-05 at 11 15 41

But when i use configOptions.set(...) like in your example it does not generate the commonMain but main sourceSet instead.

NDuering commented 7 months ago

In this case i have use this keyvalue:"sourceFolder" to "src/commonMain/kotlin", to overwrite the src folder destination name.

volkert-fastned commented 7 months ago

@charlee-dev Can you maybe share where you found the documentation for the option skipOperationModel? Because both a Google search and a search in this GitHub project yielded only one result, namely your post above. It's not listed at https://openapi-generator.tech/docs/generators/kotlin/, for example.

Thanks.

volkert-fastned commented 7 months ago

@charlee-dev Can you maybe share where you found the documentation for the option skipOperationModel? Because both a Google search and a search in this GitHub project yielded only one result, namely your post above. It's not listed at https://openapi-generator.tech/docs/generators/kotlin/, for example.

Thanks.

@NDuering I see now that you suggested this option even earlier in this thread. Perhaps you know? Thanks.

charlee-dev commented 7 months ago

@volkert-fastned, I think I got this skipOperationModel from a previous post of @NDuering. I cannot see it in my configuration anymore, so it looks like I removed it after posing it here. I finished the OpenApi Generation task.

All possible config options can be found here

Here is my final config I ended up using:

openApiGenerate {
    generatorName = "kotlin"
    packageName = group.toString()
    inputSpec = "${projectDir.path}/openapi.yml"
    typeMappings.put("string+date-time", "Instant")
    importMappings.putAll(
        mapOf(
            "Instant" to "kotlinx.datetime.Instant",
            "File" to "OctetByteArray",
        )
    )
    additionalProperties.set(
        mapOf(
            "library" to "multiplatform",
            "dateLibrary" to "kotlinx-datetime",
            "enumPropertyNaming" to "UPPERCASE",
            "useCoroutines" to "true",
        )
    )
}

Note: Adding serialization together with multiplatform breaks the generation.

volkert-fastned commented 7 months ago

Thanks, @charlee-dev. By the way, I discovered that when library is set to multiplatform, useCoroutines automatically is set to true as well, so you don't need to explicitly set it in that case. Likely that's because the Ktor client library is then used, which is built upon coroutines.