kotlinx.serialization icon indicating copy to clipboard operation
kotlinx.serialization copied to clipboard

'coerceInputValues' configuration option does not work for lists of Enums

Open PhilipSA opened this issue 5 years ago • 11 comments

Describe the bug If you have an EnumClass and the json contains an element not present in the enum it will crash: kotlinx.serialization.SerializationException: com.example.testingstuff.Numbers does not contain element with name 'Two'

But since i have declared ignoreUnknownKeys = true i expect it to be either null or default to something.

I did not find anything about this in the documentation.

Also is there any workaround for this?

To Reproduce

enum class Numbers {
    One
}

@Serializable
data class EnumClass(
    val enumType: Numbers? = null
)

class ExampleUnitTest {
    @Test
    fun ignoreUnknownEnum() {
        val json = Json {
            ignoreUnknownKeys = true
        }
        //This will work
        var jsonString = "{\"enumType\": \"One\" }"
        json.decodeFromString(EnumClass.serializer(), jsonString)

        //This will crash
        jsonString = "{\"enumType\": \"Two\" }"
        json.decodeFromString(EnumClass.serializer(), jsonString)
    }
}

Expected behavior enumType becomes null or Numbers.One

Environment

  • Kotlin version: 1.4.10
  • Library version: 1.0.0-RC2
  • Kotlin platforms: Android JVM
  • Gradle version: 4.0.1

PhilipSA avatar Oct 01 '20 15:10 PhilipSA

It works as expected, ignoreUnknownKeys is designed to ignore unknown keys, not values. But you can use coerceInputValues = true for the very purpose you described

qwwdfsad avatar Oct 01 '20 15:10 qwwdfsad

It works as expected, ignoreUnknownKeys is designed to ignore unknown keys, not values. But you can use coerceInputValues = true for the very purpose you described

Nice that worked for the example case. But what about if it is a list of enums?

It still crashes when i change my example to this:

enum class Numbers {
    One
}

@Serializable
data class EnumClass(
    val enumType: List<Numbers?>
)

class ExampleUnitTest {
    @Test
    fun ignoreUnknownEnum() {
        val json = Json {
            ignoreUnknownKeys = true
            coerceInputValues = true
        }

        var jsonString = "{\"enumType\": [\"One\"] }"
        json.decodeFromString(EnumClass.serializer(), jsonString)

        jsonString = "{\"enumType\": [\"Two\"] }"
        json.decodeFromString(EnumClass.serializer(), jsonString)
    }
}

PhilipSA avatar Oct 01 '20 15:10 PhilipSA

Currently, the only workaround is to write your own serializer. We may consider implementing this functionality as part of coerceInputValues

qwwdfsad avatar Oct 01 '20 16:10 qwwdfsad

Currently, the only workaround is to write your own serializer. We may consider implementing this functionality as part of coerceInputValues

Yes please. Consider this a feature request

PhilipSA avatar Oct 01 '20 16:10 PhilipSA

See also #1205

sandwwraith avatar Aug 13 '21 11:08 sandwwraith

I don't really have more than a 👍 to contribute, but could this perhaps be looked at in the future? We would like to either mark one enum value as @Default using List<Enum>, or receive null values with List<Enum?>, both would work.

carstenhag avatar Jan 27 '23 13:01 carstenhag

Is there any news regarding the implementation of this feature? It would be very useful to have the coerceInputValues support for lists of enums.

DrMetallius avatar Apr 05 '23 15:04 DrMetallius

.

huthe98 avatar Jan 25 '24 14:01 huthe98

This is years old. What's the latest greatest workaround? if I would like all non-matching enum values to be mapped to a specified enum value (e.g. "Unknown") - I had a solution that worked in JVM (using reflection) but in a multiplatform project, it is no longer viable. Thanks.

valeriyo avatar Aug 13 '24 01:08 valeriyo

The best workaround is to use a custom serializer that just reads/writes the value as string and maps that to the needed enum values. Writing custom serializers is actually really easy, especially that only read/write primitives.

pdvrieze avatar Aug 13 '24 18:08 pdvrieze