如何用Kotlin限制类属性整数值并让Gson序列化为数字
问题描述
需要通过枚举类限制Car类中seats属性的允许整数值,同时使用Gson序列化时,该属性输出数字类型(如5)而非字符串类型(如"5")。现有代码序列化后seats为字符串,不符合预期。
现有代码:
class Car( @Expose val color: Color = Color.RED, @Expose val seats: Seats = Seats.FIVE // 用枚举限制预定义值 ) enum class Color{ @SerializedName("red") RED, @SerializedName("blue") BLUE, } enum class Seats{ @SerializedName("4") FOUR, @SerializedName("5") FIVE, }
当前序列化输出:
{ "color": "red", "seats": "5" // 字符串类型,不符合需求 }
期望输出:
{ "color": "red", "seats": 5 // 数字类型 }
解决方案
核心思路是给枚举类绑定对应的整数值,通过自定义TypeAdapter控制Gson的序列化/反序列化逻辑,让枚举输出为数字。
步骤1:修改Seats枚举类,添加整数值属性
给每个枚举常量绑定对应的整数,替代原来的@SerializedName字符串:
enum class Seats(val value: Int) { FOUR(4), FIVE(5) }
步骤2:自定义Seats的TypeAdapter
实现Gson的TypeAdapter接口,控制序列化时输出枚举对应的整数,反序列化时把整数映射回枚举:
class SeatsTypeAdapter : TypeAdapter<Seats>() { // 序列化:把Seats枚举转为对应的整数 override fun write(out: JsonWriter, value: Seats?) { value?.let { out.value(it.value) } } // 反序列化:把整数转为对应的Seats枚举,非法值抛出异常 override fun read(`in`: JsonReader): Seats? { val intValue = `in`.nextInt() return Seats.values().firstOrNull { it.value == intValue } ?: throw JsonSyntaxException("无效的seats值: $intValue") } }
步骤3:注册TypeAdapter到Gson
有两种注册方式,选其一即可:
方式A:在枚举类上添加@JsonAdapter注解
直接在Seats枚举类上标注,指定使用自定义的适配器:
import com.google.gson.annotations.JsonAdapter @JsonAdapter(SeatsTypeAdapter::class) enum class Seats(val value: Int) { FOUR(4), FIVE(5) }
方式B:创建Gson实例时注册适配器
在构建Gson对象时显式注册SeatsTypeAdapter,同时保留@Expose的过滤逻辑:
val gson = GsonBuilder() .registerTypeAdapter(Seats::class.java, SeatsTypeAdapter()) .excludeFieldsWithoutExposeAnnotation() // 保留只序列化带@Expose的字段 .create()
测试效果
序列化示例:
val car = Car(seats = Seats.FIVE) val json = gson.toJson(car) println(json)
输出结果:
{"color":"red","seats":5}
反序列化示例:
val jsonStr = """{"color":"blue","seats":4}""" val car = gson.fromJson(jsonStr, Car::class.java) println(car.seats) // 输出:FOUR
内容的提问来源于stack exchange,提问作者Crocodile
相关产品推荐
相关产品推荐

