How use Kotlin enum with Retrofit?

16,243

Solution 1

enum class VehicleEnumEntity(val value: String) {
   @SerializedName("vehicle")
   CAR("vehicle"),

   @SerializedName("motorcycle")
   MOTORCYCLE("motorcycle"),

   @SerializedName("van")
   VAN("van"),

   @SerializedName("motorhome")
   MOTORHOME("motorhome"),

   @SerializedName("other")
   OTHER("other")
}

Source

Solution 2

Another option: use a custom (de)serializer that uses the value of the enum, instead of the name (default). This means you don't need to annotate every enum value, but instead you can annotate the enum class (or add the adapter to GsonBuilder).

interface HasValue {
    val value: String
}

@JsonAdapter(EnumByValueAdapter::class)
enum class VehicleEnumEntity(override val value: String): HasValue {
   CAR("vehicle"),
   MOTORCYCLE("motorcycle"),
   VAN("van"),
   MOTORHOME("motorhome"),
   OTHER("other")
}

class EnumByValueAdapter<T> : JsonDeserializer<T>, JsonSerializer<T>
    where T : Enum<T>, T : HasValue {
    private var values: Map<String, T>? = null

    override fun deserialize(
        json: JsonElement, type: Type, context: JsonDeserializationContext
    ): T? =
        (values ?: @Suppress("UNCHECKED_CAST") (type as Class<T>).enumConstants
            .associateBy { it.value }.also { values = it })[json.asString]

    override fun serialize(
        src: T, type: Type, context: JsonSerializationContext
    ): JsonElement = JsonPrimitive(src.value)
}

The same adapter class is reusable on other enum classes.

Share:
16,243

Related videos on Youtube

Pasha Shkaran
Author by

Pasha Shkaran

Updated on June 26, 2022

Comments

  • Pasha Shkaran
    Pasha Shkaran almost 2 years

    How can I parse JSON to model with enum?

    Here is my enum class:

    enum class VehicleEnumEntity(val value: String) {
       CAR("vehicle"),
       MOTORCYCLE("motorcycle"),
       VAN("van"),
       MOTORHOME("motorhome"),
       OTHER("other")
    }
    

    and I need to parse type into an enum

    "vehicle": { "data": { "type": "vehicle", "id": "F9dubDYLYN" } }

    EDIT

    I have tried standard way, just pass my enum to POJO and it always null

    • lelloman
      lelloman over 6 years
      have you tried somethinig?
    • Pasha Shkaran
      Pasha Shkaran over 6 years
      @lelloman yes, I have tried standard way, just pass my enum to POJO and it always null
    • lelloman
      lelloman over 6 years
      maybe it's worth mentioning it in your question
    • LordRaydenMK
      LordRaydenMK over 6 years
      I think the most relevant part here would be which converter are you using... GSON or something else?
    • Pasha Shkaran
      Pasha Shkaran over 6 years
      @LordRaydenMK yes GSON
    • LordRaydenMK
      LordRaydenMK over 6 years
      have you tried using @SerializedName annotation? according to this stackoverflow.com/questions/25423590/enum-annotations-in-kot‌​lin it should work
  • Blundell
    Blundell over 3 years
    that's a GSON solution, change to @Json(name="foo") for moshi
  • LordRaydenMK
    LordRaydenMK over 3 years
    @ravidrinek please ask a new question, and include all relevant details, e.g. json parsing lib etc...
  • Sergio
    Sergio over 3 years
    This works nicely if the enum type is String. Is there a way to create a generic adapter for any type? The most common enum values are strings and integers I think, but it would be nice to have a generic way to serialize any type.