kotlin safe conversion from string to enum
Solution 1
You don't want an extension since they must be invoked on an existing object. You want a top-level function. There is a built in one You can use:
/**
* Returns an enum entry with specified name.
*/
@SinceKotlin("1.1")
public inline fun <reified T : Enum<T>> enumValueOf(name: String): T
You can call it by inferring the type, or explicitly:
val a : MyEnumClass = enumValueOf("A")
val b = enumValueOf<MyEnumClass>("B")
However this method is not nullable: it throws java.lang.IllegalArgumentException
on unknown values.
But it's easy to mimick it's behavior and have it work for nullable enums with a top level function:
inline fun <reified T : Enum<*>> enumValueOrNull(name: String): T? =
T::class.java.enumConstants.firstOrNull { it.name == name }
Solution 2
Colors.values().find { it.name == "Yellow" }
Solution 3
You can use something like this :
inline fun <reified T : Enum<T>> String.asEnumOrDefault(defaultValue: T? = null): T? =
enumValues<T>().firstOrNull { it.name.equals(this, ignoreCase = true) } ?: defaultValue
Then: "Yellow".asEnumOrDefault(Colors.Green)
Or, if you it can't be infered: "Yellow".asEnumOrDefault<Colors>()
Related videos on Youtube
innov8
Updated on September 14, 2022Comments
-
innov8 over 1 year
I need to convert strings to Enum values, but want a function which returns null if the string is not an enum.
enum class Colors{ Red, Green, Blue }
I can used Colors.valueOf(testString) provided testString is value, but there will be an exception if it is not valid, and I want a null in that case.
Because I want to this often, an extension function would be ideal. But the extension needs to operate on the class Colors, and not an object of type Colors.
Anyone know how to write such an extension? Ideally one that is generic for any enum class.
It is simple to write a top level function, but I am seeking one that acts as the standard 'method' does
// instead of val willGetAnException = Colors.valueOf("Yellow") // standard existing fun val willGetNull = Colors.valueOrNullOf("Orange") // new fun i seek
And ideally one that is generic and works for any enum
-
innov8 over 5 yearsThanks... that is about the point i got to as well..... if i make that function a method of the companion object of the class (and take out the generic) I can call it the way i wish.
-
Pawel over 5 yearsIf you want it to be limited to single enum class you could have added method in companion object that wraps
valueOf
with a try-catch block. -
innov8 over 5 yearsThanks... that is about the point i got to as well. A top level function which is not what i want. Sort of one step further ..... if i make that function a method of the companion object of the enum class (and take out the generic) I can call it the way i wish. But how to have a generic method apply to the companion object of all enum classes is what i was hoping for,
-
con over 3 yearsa verbal explanation is often helpful
-
Emanuel Moecklin about 3 yearsThis is a very simple and elegant solution without the need for extension functions. You can also define a default value using the Elvis operator: Colors.values().find { it.name == "Yellow" } ?: Colors.Red
-
Denis Pavlov over 2 yearsThis is an elegant solution. Thanks.
-
Mick Sear over 2 yearsBest solution IMHO. If you want to default it then just do
val colour = Colors.values().find { it.name == "Yellow" } ?: Colors.UNKNOWN
or something like that.