micronaut-projects / micronaut-openapi

Generates OpenAPI / Swagger Documentation for Micronaut projects
https://micronaut-projects.github.io/micronaut-openapi/latest/guide/index.html
Apache License 2.0
80 stars 95 forks source link

Allow for Jackson Setting customization for case insenstive enum serde #1760

Closed scprek closed 2 months ago

scprek commented 2 months ago

Expected Behavior

Allow these application configuration settings to work and accept case insensitive enums

openapi-generator-cli generate -i openapi.json -g kotlin -o output/directory -p library=jvm-spring-restclient,serializationLibrary=jackson,useSpringBoot3=true --skip-validate-spec
jackson:
    mapper:
        ACCEPT_CASE_INSENSITIVE_PROPERTIES: true
        ACCEPT_CASE_INSENSITIVE_ENUMS: true

Upstream Example

enum class CurrencyType(val value: kotlin.String) {

    @JsonProperty(value = "USD")
    USD("USD"),

    @JsonProperty(value = "CAD")
    CAD("CAD");

    override fun toString(): kotlin.String = value

    companion object {
        fun encode(data: kotlin.Any?): kotlin.String? = if (data is CurrencyType) "$data" else null

        fun decode(data: kotlin.Any?): CurrencyType? = data?.let {
          val normalizedData = "$it".lowercase()
          values().firstOrNull { value ->
            it == value || normalizedData == "$value".lowercase()
          }
        }
    }
}

Actual Behaviour

Cannot construct instance of `com.test.model.CurrencyType`, problem: Unexpected value 'usd'
    companion object {

        @JvmField
        val VALUE_MAPPING = entries.associateBy { it.value }

        /**
         * Create this enum from a value.
         *
         * @param value value for enum
         *
         * @return The enum
         */
        @JsonCreator
        @JvmStatic
        fun fromValue(value: String): CurrencyType {
            require(VALUE_MAPPING.containsKey(value)) { "Unexpected value '$value'" }
            return VALUE_MAPPING[value]!!
        }
    }

Steps To Reproduce

  1. Create an enum with upper case
  2. send api request/response with lower case

Environment Information

Example Application

No response

Version

4.5.1

altro3 commented 2 months ago

This is bug in micronaut-serilization, generted code is fine

altro3 commented 2 months ago

Or, maybe I'm wrong. Is it work with jackson?

scprek commented 2 months ago

I guess normally with Jackson and enum classes, I don't make a custom method and annotate as json creator. By default it just works? And then when you set those properties on the mapper it automatically handles all the cases

I tried a few kotlin generators all with Jackson and they all did the unannotated companion object encode/decode. Not sure why even the spring one has it

altro3 commented 2 months ago

Yes, I was wrong. Even in the templates there was a mention of the useEnumCaseInsensitive setting, it was just impossible to set it via the plugin. Also, I improved the templates a little bit so that the generated code was perfect.

scprek commented 2 months ago

So when a new option is added here does it always require a change to the gradle plugin too? Like https://github.com/micronaut-projects/micronaut-gradle-plugin/commit/83dd0697500ea970ae3a2aaba6cdddedf9f22c73 to add the interface option.

Or is there some dynamic way the plugin can handle new options added?

Just curious

altro3 commented 2 months ago

Yes, I agree, it is inconvenient. I don't know why it was done this way, I just added new properties. I myself thought that it would be necessary to add some block with dynamic properties, so as not to depend on the plugin.