You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:12:48