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

Fallback value for unknown enum values

Open Nohus opened this issue 4 months ago • 3 comments

When deserializing enum values, it would be useful to specify a fallback value, in case a remote API introduces a new value for the enum.

Example:

enum class Color {
    Red,
    Green,
    @FallbackEnumValue
    Unknown,
}

data class Scarf(val colors: List<Color>)

Then, the following JSON:

{ "colors": ["Green", "Blue", "Red"] }

Would result in:

Scarf(listOf(Green, Unknown, Red))

Another use case would be an API returning an enum with many possible values, where the client only cares about a subset of them, and would like to consider all other as a single "Other" value.

This is supported in Jackson as @JsonEnumDefaultValue.

There was a similar issue #90, but it asked for the ability to use the default value as declared on the use site of the enum, which is different and not applicable to the above example.

Nohus avatar Aug 08 '25 12:08 Nohus

I think an equivalent to coerceInputValues but as an annotation for use-site would also be nice and support null:

@Serializable
data class Something(
    @CoerceInputValues val type: Type? = null
)

Could also be called @SerializeDefaultOnUnkown, or something else.

LouisCAD avatar Aug 27 '25 11:08 LouisCAD

@LouisCAD What you are describing is more of a solution for the other issue I linked.

  • I am looking for a declaration-side solution, so that you don't need to do it in 20 places if you use that enum in 20 places.
  • It wouldn't work for collections, like my example shows.
  • You might want a default value that's different from the fallback value, so coercing to default doesn't work for all cases. For example val color: Color? = null, I want null if there is no color sent, but Unknown if there is a color, but the client doesn't support it. The API not sending a value is a normal valid case, where it sending an unknown value needs to be handled differently.

Nohus avatar Aug 27 '25 11:08 Nohus

On the other hand, the issue you linked was closed without any such solution, nor reply from the concerns of putting it at the use-site.

There are basically 3 levels, and depending on the project's specifics, we might need a different level:

  1. Json { … } config level (already implemented to some extent with coerceInputValues, lacks connection to the affect symbols, no fine-grained control)
  2. enum declaration level (what you are asking for), works everywhere the enum is used.
  3. use-site (what I also want as an option), works where the enum is used, if specified, and nowhere else.

I think we can have this issue be about those 2 latter levels, unless a maintainer asks us to split it, or decides to provide a solution for only one of the 2 missing levels (🥲), do you agree?

LouisCAD avatar Aug 27 '25 14:08 LouisCAD

Hi @sandwwraith if someone opens a PR for this issue will that be accepted or in other words does serialisation team agree that this feature should be present in the Serialisation lib?

@Nohus did you find some workaround?

atulgpt17 avatar Dec 15 '25 09:12 atulgpt17

I think this should eventually be supported, yes. However, it requires careful design to determine whether we should also implement something similar to what @LouisCAD suggested: allowing this annotation on properties, not just enum entries, and whether it should be the same annotation. I do not see, for now, compelling use cases for property-level.

sandwwraith avatar Dec 15 '25 13:12 sandwwraith

The problem with property level annotations for non-enum values (for defaults or fallbacks) is that annotations can only have limited value types. For enums it works if the value used is the serialName of the enum value to use. For others it is a challenge.

pdvrieze avatar Dec 15 '25 21:12 pdvrieze