[REQ][Kotlin] Use mutable container types when 'modelMutable' is enabled
Created by: rm3l
Hi there!
I am opening this feature request to gather some feedback. If you think this feature request makes sense, I can try to contribute a PR, after finding my way around the code :-)
Is your feature request related to a problem? Please describe.
At this time, the Kotlin generators always generate immutable types (Map
, List
or Set
) for OpenAPI containers like dictionaries and arrays.
Kotlin separates collections for read-only and read/write access purposes. Read/Write access is supported through the MutableCollection and MutableMap interfaces.
So I would expect those types to be used instead for containers when setting modelMutable
to true
.
Example Given the following definition:
openapi: 3.0.3
info:
title: 'modelMutable and Kotlin container types'
version: 0.1.0
paths:
'/':
get:
operationId: myOperation
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/MyModel'
components:
schemas:
MyModel:
description: Model with properties that should be mutable in Kotlin
properties:
myIntArray:
type: array
items:
type: integer
myStringSet:
type: array
items:
type: string
uniqueItems: true
myFreeFormObject:
type: object
additionalProperties:
type: object
Here is the resulting model generated by the Kotlin generators (I tested both kotlin-spring
and kotlin
), using openapi-generator 5.3.0:
//Annotations omitted for brevity
data class MyModel(
var myIntArray: kotlin.collections.List<kotlin.Int>? = null,
var myStringSet: kotlin.collections.Set<kotlin.String>? = null,
var myFreeFormObject: kotlin.collections.Map<kotlin.String, kotlin.Any>? = null
) {
}
In the example above, if I want to add / remove something from these containers, I need to explicitly convert the read-only type generated by the OpenAPI Generator into its mutable counterpart, apply my changes, then reassign it like so:
//copy as a mutable container
val myIntArrayMutable = myModel.myIntArray?.toMutableList()
//apply mutation operation and re-assign
myIntArrayMutable?.add(42)
myModel.myIntArray = myIntArrayMutable
This, IMHO, makes it not that straightforward to update such fields, when mutability is purposely needed from generated Kotlin code.
Also, converting from immutable to mutable containers may incur some runtime performance penalty, as new objects are instantiated and container items are copied there.
For reference, here is the command used for generation:
openapi-generator-cli generate \
-i /path/to/openapi.yaml \
-g kotlin-spring \
-o /tmp/test-openapi-kotlin-spring \
--additional-properties=modelMutable=true
Describe the solution you'd like
Kotlin separates collections for read-only and read/write access purposes. Read/Write access is supported through the MutableCollection and MutableMap interfaces.
So I would expect those types to be used instead for containers when setting modelMutable
to true
.
Here is how I would expect the generated model to be, using the example above:
//Annotations omitted for brevity
data class MyModel(
var myIntArray: kotlin.collections.MutableList<kotlin.Int>? = null,
var myStringSet: kotlin.collections.MutableSet<kotlin.String>? = null,
var myFreeFormObject: kotlin.collections.MutableMap<kotlin.String, kotlin.Any>? = null
) {
}
This would allow to mutate the original container right away, without having to copy all its items to a mutable container:
//apply mutation operation right away on the original collection
myModel.myIntArray?.add(42)
Describe alternatives you've considered
Whenever mutability is needed (like updating an object from a remote API and sending it back), I explicitly convert the read-only collection field into its mutable counterpart, apply my changes, then reassign it.