455 字
2 分钟
Gson忽略不能/不需要被序列化或反序列化的字段Kotlin
2024-10-26
无标签

起因#

我在写ROneBot的时候遇到一个问题: 在 所有的原始json字符串被反序列化成Kotlin数据类实体的时候我需要添加一个OneBotAction对象 在这个数据类中, 但是这个OneBotAction中有一个Websocket对象, 这个对象不能被反序列化或者 序列化成json, 所以我想到了Gson自带的@Expose注解, 但是这个注解只能用于将某个字段暴露 而不是忽略, 想实现忽略也可以但是你需要手动的把所有需要 的字段使用@Expose注解, 这样超级麻烦所以就有了这篇文章

不用添加自定义注解的解决方案#

这个方案是我从gpt问来的(我最诚实), 就是使用 @Transient这个注解来注解一个字段 这个注解是Kotlin标准库的注解, 被注解之后Gson就会忽略这个字段的序列化和反序列化

原理#

添加一个自己的注解然后写一个策略类忽略被这个注解注解过的字段

代码#

首先创建一个自定义注解

/**
 * 自定义注解标注了哪些字段可以不被序列化/反序列化
 */
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
annotation class ExcludeField

然后创建一个自定义策略

/**
 * 创建自定义Exclude策略用于不处理被[ExcludeFiled]注解的属性
 */
class ExcludeStrategy : ExclusionStrategy {
    override fun shouldSkipField(f: FieldAttributes): Boolean {
        return f.getAnnotation(ExcludeFiled::class.java) != null
    }

    override fun shouldSkipClass(clazz: Class<*>?): Boolean {
        return false
    }
}

应用这个自定义注解

val gson: Gson = GsonBuilder()
    .disableHtmlEscaping()
    .addSerializationExclusionStrategy(ExcludeStrategy())
    .addDeserializationExclusionStrategy(ExcludeStrategy())
    .create()

这样就大功告成了, 只要是被这个注解注解过的字段gson都会忽略这个字段

使用例子#

data class GroupMessage(
    // 这里的OneBotAction会被gson忽略
    @ExcludeFiled
    var action: OneBotAction,
    @SerializedName("group_id")
    val groupId: Long,
    var sender: GroupSender
    ...
)