Reputation: 1481
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
Upvotes: 39
Views: 25422
Reputation: 190
If you are using kotlinx.serialization
, then you simply need to mark your enum class as @Serializable
and use @SerialName
with it's values:
@Serializable
enum class VehicleEnumEntity(val value: String) {
@SerialName("vehicle")
CAR("vehicle"),
@SerialName("motorcycle")
MOTORCYCLE("motorcycle"),
@SerialName("van")
VAN("van"),
@SerialName("motorhome")
MOTORHOME("motorhome"),
@SerialName("other")
OTHER("other")
}
Upvotes: 2
Reputation: 750
In case the backend service responses integers for example. You can you change the constructor parameter as Int
.
enum class Day(val rawValue: Int) {
@SerializedName("1")
SUNDAY(1),
@SerializedName("2")
MONDAY(2),
@SerializedName("3")
TUESDAY(3),
@SerializedName("4")
WEDNESDAY(4),
@SerializedName("5")
THURSDAY(5),
@SerializedName("6")
FRIDAY(6),
@SerializedName("7")
SATURDAY(7),
@SerializedName("-1")
UNSUPPORTED(-1);
companion object {
fun from(findValue: Int): Day = values().firstOrNull { it.rawValue == findValue } ?: UNSUPPORTED
}
}
Nitpick: The from
function helps you to find an enum value easily by a given Int
.
Upvotes: 3
Reputation: 204778
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.
Upvotes: 16
Reputation: 13321
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")
}
Upvotes: 97