Serialize enum differently based on context

We’re using Kotlin with Android and have an interesting use case for enums. We’ve got an Event, which can have several types, let’s say CALL, EMAIL, and SMS. We need this data in two places, obviously we need to be able to serialize to the all-caps versions for Gson to be able to parse our API requests properly, but we also need to be able to automatically serialize to sentence-case (Call instead of CALL) because we want easy-to-read values in a spinner that we use to allow the user to select which event type they want to look at. Is there any easy way to do this without registering an Event type adapter with Gson?

Posting for posterity. We ended up rolling our own solution to this. Rather than explaining, I’ll just provide a (contrived) code sample:

enum class Event {
  CALL,
  EMAIL,
  SMS
}

class Option<T> (
    val value: T,
    val displayName: String
) {
  override fun toString(): String = displayName
}

val options = listOf(Event.CALL, Event.EMAIL, Event.SMS)
        .map { Option(it, it.name.toLowerCase.capitalize() }

val adapter = ArrayAdapter(context, R.layout.my_spinner_item, options)

It’s not the most beautiful, but works for us. Then you simply pass option.value into your model/API request instead of just option. Would still be interested in hearing if anyone has encountered this before/has a better solution.

One thing you can do with enums is add a custom field, set in the constructor. And if you’re on Android you can use localized resources to get something like this :

enum class Event(val res : Int) {
    CALL(R.string.option_call),
    EMAIL(R.string.option_email),
    SMS(R.string.option_sms)
}

val options = listOf(Event.CALL, Event.EMAIL, Event.SMS)
            .map { Option(it, context.getString(it.res) }

val adapter = ArrayAdapter(context, R.layout.my_spinner_item, options)

If you don’t need the localization, you can still just set a custom name like this :

enum class Event(val display : String) {
    CALL("Call"),
    EMAIL("E-mail"),
    SMS("S.M.S.")
}
2 Likes