I'd like to limit the permitted integer values for a class property, in a way that after serialisation to Json (with gson) the value would be represented as a number and not as a string.
class Car(
@Expose val color: Color = Color.RED,
@Expose val seats: Seats = Seats.FIVE // Using an enum class so only predefined values are accepted.
)
enum class Color{
@SerializedName("red") RED,
@SerializedName("blue") BLUE,
}
enum class Seats{
@SerializedName("4") FOUR,
@SerializedName("5") FIVE,
}
Actual json output:
{
"color": "red",
"seats": "5" // This is a string. It's not what I want.
}
The json output I need:
{
"color": "red",
"seats": 5 // This is a number ✓
}
If you really want to stick to Gson, one way of doing this is to specify the integer as a property of the enum:
enum class Seats(val value: Int) {
FOUR(4),
FIVE(5);
companion object {
fun of(value: Int) = entries.firstOrNull { it.value == value }
}
}
Then use a type adapter or custom serializer that uses this property for serialization, and the Seat.of(...)
function for deserialization:
class SeatSerializer : JsonSerializer<Seats> {
override fun serialize(src: Seats, typeOfSrc: Type, context: JsonSerializationContext): JsonElement =
JsonPrimitive(src.value)
}
class SeatDeserializer : JsonDeserializer<Seats> {
override fun deserialize(element: JsonElement, type: Type, context: JsonDeserializationContext): Seats =
Seats.of(element.asInt) ?: error("Cannot deserialize ${element.asInt} as Seats")
}