Kotlin enum class serialization

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SerialName for Enums #31

SerialName for Enums #31

Comments

It’s quite common case when deserialization of JSON you want to parse some property to Enum constant, but now Enum constant should have the same name and same case as a property value.
Would be nice to allow annotate enums with SerialName to provide custom naming for a serilized format.
An alternative solution is to use Serializer but looks like overkill for enum classes and SerialName could replace it.

Читайте также:  Python datetime now with timezone

The text was updated successfully, but these errors were encountered:

I’m surprised that this hasn’t been implemented yet, as this is pretty basic.

Here is a generic Enum serializer that uses @SerializedName annotation on Enum fields.

NOTE 1: The contents of companion object are 100% reusable, and could be moved out into common code/library.

NOTE 2: The «UNKNOWN» fallback value allows forward compatibility, so that old client doesn’t crash when receiving an unknown enum value (because it was introduced later), so that it can log it and ignore — instead of crashing.

NOTE 3: The EnumSerialNameSerializer could be modified to be more lenient (e.g. case-insensitive) if necessary.

Perhaps, there is a better way of doing this? Let me know.

package com.example import kotlinx.serialization.Decoder import kotlinx.serialization.Encoder import kotlinx.serialization.KSerializer import kotlinx.serialization.SerialDescriptor import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.enumMembers import kotlinx.serialization.internal.StringDescriptor import kotlin.reflect.KClass class Linter < @Serializable(with = LintSeveritySerializer::class) enum class LintSeverity < @SerialName("error") ERROR, @SerialName("warning") WARNING, @SerialName("auto_fix") AUTOFIX, @SerialName("advice") ADVICE, @SerialName("disabled") DISABLED, UNKNOWN > object LintSeveritySerializer : EnumSerialNameSerializerLintSeverity>( LintSeverity::class, fallback = LintSeverity.UNKNOWN ) @Serializable private class LintMessage( val path: String, val line: Int? = null, val char: Int? = null, val severity: LintSeverity ) companion object < open class EnumSerialNameSerializerE : EnumE>>( private val kClass: KClassE>, private val fallback: E ) : KSerializer < override val descriptor: SerialDescriptor = StringDescriptor override fun serialize(encoder: Encoder, obj: E) < encoder.encodeString(obj.getEnumFieldAnnotationSerialName>()!!.value) > override fun deserialize(decoder: Decoder): E = decoder.decodeString().let < value -> kClass.enumMembers() .firstOrNull < it.getEnumFieldAnnotationSerialName>()?.value == value > ?: run < // TODO: Log an error/warning? fallback > > > inline fun reified A : Annotation> Enum*>.getEnumFieldAnnotation(): A? = javaClass.getDeclaredField(name).getAnnotation(A::class.java) > >

Источник

enum in Kotlin

In this article, we will discuss the enum in Kotlin. If you use Kotlin for Android or Spring, still this concept holds the same.

2. Enum classes

An Enum is a class that represents a group of constants. You can always use enums when a variable can only accept value out of a small set of known values. Examples would be things like type constants (directions: NORTH, SOUTH, EAST, WEST), or flags (Started, Paused, In progress, Completed).

The most basic use case for enum classes is the implementation of type-safe enums. It increases compile-time checking and avoid errors from passing in invalid constants. You can also document which values are valid to use and what it implies.

The enum constants are separated by commas and each of them is an object.

In the below example, enum constants GOLD, SILVER, BRONZE are all objects separated by commas.

2.1 Kotlin enum constructor

Since each enum is an instance of the enum class, we can initialize variables using the constructor as below. These variables would be final so we can’t change at runtime. This allows you to pass parameters to enum class.

In this example, we have declared a variable rgb in the constructor of the enum class Color to hold the color code. Later, you can reference it to get the corresponding color code of any color. Integer.toHexString(Color.RED.rgb) would return the color code ff0000.

enum class Color(val rgb: Int) < RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF) >fun main() < val color = Color.RED if (color is Enum) < println(Integer.toHexString(color.rgb)) println(true) >>

2.1. enum in Kotlin example

Let’s take an enum example.

Suppose you want to track the user’s movement and the direction they are heading towards. For this, you would create a function that should process the user’s direction and should accept only the geographical directions as input.

We already know the directions available: NORTH, SOUTH, EAST, WEST. So let’s create an enum Direction with those constant values.

Let the function be named getUserDirection which accepts only the enum of type Direction . You can only pass enum constants to this function. Also note the print statement. Here, we are printing the name of the enum constant using the attribute name of enum class ( direction.name ).

enum class Direction < NORTH, SOUTH, WEST, EAST >fun getUserDirection(direction : Direction) < println(direction.name) >fun main()

If you pass anything else apart from the Direction’s enum constant, then the compiler would throw a warning. This would allow you to do compile time checking and prevent any runtime errors.

The above code will throw compilation warning “Type mismatch: inferred type is String but Direction was expected”

2.2. Kotlin enum default value

Kotlin doesn’t assign any default value to Enum constants or enum objects. But you can manually set any value to your enum constant.

Let’s see an easy example to understand this case. In this enum class, we are passing an Int value to enum constants DOG, CAT and FISH. This value would be final and you can’t change at runtime. So each enum constant would have a default value but it is final.

enum class Animal(val animalId: Int)

3. Enum Anonymous classes and method

Enum constants can declare their own anonymous classes with their corresponding methods. It can also override the base methods.

In the below example, Enum class defines an abstract base method getAmount . Each enum constant has declared an anonymous class in which it has overridden that base method getAmount .

You should separate the enum constants from the members using the semicolon. Note that we have a semicolon between the base method and the enum constants.

enum class SalaryAmount < WITH_HIKE < override fun getAmount(currentSalary: Long) : Long < return currentSalary + 10000 >>, WITHOUT_HIKE < override fun getAmount(currentSalary: Long) : Long < return currentSalary >>; abstract fun getAmount(currentSalary: Long): Long > fun main()

4. Implementing interfaces in enum classes

An enum class can implement an interface providing either a common implementation of interface members for all the enum constants, or separate implementations for each constant within its anonymous class.

Note that enum class can’t extend class. It can implement one or more interfaces.

Let’s take the same Salary example which we have seen in previous section.

Here, Enum class SalaryAmount implements the interface Amount with two abstract functions getAmount and getName . Each enum constant implements the getAmount method separately within its anonymous class whereas enum class provides a common implementation of getName that applies to all the enum constants.

When you call getName method on any of the enum constant, it would go to the common implementation and prints TedBlob .

interface Amount < fun getAmount(currentSalary: Long): Long fun getName() : String >enum class SalaryAmount : Amount < WITH_HIKE < override fun getAmount(currentSalary: Long) : Long < return currentSalary + 10000 >>, WITHOUT_HIKE < override fun getAmount(currentSalary: Long) : Long < return currentSalary >>; override fun getName() : String < return "TedBlob" >> fun main()

5. enum valueof kotlin

To get an enum constant by its name, you can use the function valueOf() on the Enum class. It helps us to get enum from String in Kotlin.

The return type of this function would be enum constant. If you pass the string, you can get an enum constant which you can use later to call functions or perform any other operations.

The enum valueOf() method throws an IllegalArgumentException if the specified enum type has no constant with the specified name.

The signature of this method is:

In the below example, you are passing the string “RED” to the method valueOf. It returns the enum constant object as “RED” exists in the Enum class.

Later, you pass that object to getBugState method to know the bug state.

enum class Color(val rgb: Int) < RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF) >val color : Color = Color.valueOf(«RED») println(getBugState(color)) fun getBugState(color: Color)

6. Kotlin get list of enum values

You can use values() to get the enum constants as a list. If you see the below example, Color.values() would return Array and you can convert it to Kotlin list using toList() method.

If you like join all the enum constant names as string with comma separated, then use joinToString.

enum class Color(val rgb: Int) < RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF) >println(Color.values().joinToString < it.name>) println(Color.values().toList())

Result:
RED, GREEN, BLUE

7. Kotlin enum static method

Kotlin already has static methods like values and valueOf . What if, you want to create a custom static method for your enum class to serve your own purpose.

It is simple. Just like you do in Kotlin class, create a companion object and place your static method there. You can refer to our article on Companion object, static members in Kotlin.

In the below code, random() is a static method and you can call it using enum class name Shape.random() .

8. Get enum by value Kotlin

Suppose, you want to get the enum constant using its value. First, you can use values() method of Enum to get all the enum constants of the enum class as an array. Next, you can find the enum constant by using its value.

In the below code, Enum class has a variable rgb and each enum constant has a value associated with it.

Let’s consider that you have rgb color code 0x00FF00 but you are not sure of its color and need to find it. So you created the findColor() function. Inside that function, you call values() function to get all the enum constants as array. Then using array’s find method, you can find the matching enum constant for the passed int value.

enum class Color(val rgb: Int) < RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF); companion object < fun getByValue(value: Int) = Color.values().find < it.rgb == value >> > fun main()

9. Kotlin enum ordinal

Ordinal is nothing but the position or placement of the enum constant in the enum class. It is just like an array index starting from 0. The below code would return 2 as the position of BLUE enum constant in the Color class is at index 2.

enum class Color(val rgb: Int) < RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF); >fun main()

10. Kotlin Switch enum

When defines a conditional expression with multiple branches. It is like the switch statement in Java. Suppose you want to use enum in when statement, then you can do it.

In the below example, we are using enum constants as condition in the when expression.

enum class Color(val rgb: Int) < RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF) >fun main() < bugState(Color.BLUE) >fun bugState(color: Color) < when (color) < Color.RED -> < println("Bug is in red. You should fix it") >Color.GREEN -> < println("Bug fixed") >Color.BLUE -> < println("Testing in progress") >> >

10.1. Kotlin enum switch using int

Suppose, you want to use values or integers of enum constants as condition in the when expression. Kotlin directly doesn’t support it. But we can follow the below approach to achieve it.

You can refer the section Get enum by value Kotlin to understand how we can get enum constant from its value.

In this example, we are getting the enum constant of the corresponding int value. Using fromInt function, you can get the right enum constant (like Animal.DOG) from the int value. Then you can pass the enum constant as condition in when expression.

fun getAnimalName(animal: Animal?) < animal?.let < when(animal) < Animal.DOG -> < println("DOG") >Animal.CAT -> < println("CAT") >Animal.FISH -> < println("FISH") >> > > enum class Animal(val animalId: Int) < DOG(0), CAT(1), FISH(2); companion object < fun fromInt(value: Int) = Animal.values().find < it.animalId == value >> > fun main()

11. Kotlin enum serialization

You can serialize the enum constant (enum object) as Json in Kotlin by annotating the enum property with @JsonValue or @JsonFormat (if you use jackson library version < 2.9).

Let’s see an example to understand this.

Note the @JsonValue annotation to the event parameter in the Event enum class. This will allow the Jackson library to serialize or deserialize the field in Json.

enum class Event(@JsonValue val event: String) < START("start"), END("end"), RESCHEDULE("rescheduled") >data class EventClass ( val id: String, val event: Event ) EventClass(id = «1001», event = Event.RESCHEDULE) .let < jacksonObjectMapper().writeValueAsString(it) >.let

@JsonValue annotation will not work with the enum field if you use jackson library less than 2.9. In that case, you had to use @JsonFormat annotation to achieve the same result as above.

enum class Event(@JsonFormat(shape = JsonFormat.Shape.OBJECT) val event: String) < START("start"), END("end"), RESCHEDULE("rescheduled") >data class EventClass ( val id: String, val event: Event ) EventClass(id = «1001», event = Event.RESCHEDULE) .let < jacksonObjectMapper().writeValueAsString(it) >.let

12. Conclusion

In this article, we learned about the enum class in Kotlin.

Источник

Оцените статью