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

如何在Jackson序列化Kotlin API模型时排除NO_OP默认值字段?

当然可以做到!Jackson有几种适配你这种空对象模式的方案,我给你拆解一下最实用的几种:

方案1:自定义JSON包含过滤规则(最推荐)

Jackson的@JsonInclude注解支持自定义过滤条件,我们可以直接判断字段值是否为NO_OP单例,是的话就不把该字段包含到生成的JSON中。

步骤1:创建全局过滤规则

先定义一个过滤对象,用来识别ClassOne.NO_OP和ClassTwo.NO_OP:

object NoOpFilter : JsonInclude.IncludeFilter() {
    override fun equals(value: Any?): Boolean {
        // 用引用相等判断,确保只匹配单例NO_OP
        return value === ClassOne.NO_OP || value === ClassTwo.NO_OP
    }
}

步骤2:给数据类添加注解

把这个过滤规则应用到你的MyParam类上,这样所有字段都会自动检查是否为NO_OP:

@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = NoOpFilter::class)
data class MyParam(
    val name: String,
    val myField1: ClassOne = ClassOne.NO_OP,
    val myField2: ClassTwo = ClassTwo.NO_OP
)

灵活调整:针对单个字段设置

如果你不想全局应用,只想给特定字段单独配置,可以直接在字段上添加注解:

data class MyParam(
    val name: String,
    @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = ClassOneNoOpFilter::class)
    val myField1: ClassOne = ClassOne.NO_OP,
    @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = ClassTwoNoOpFilter::class)
    val myField2: ClassTwo = ClassTwo.NO_OP
)

// 针对ClassOne的单独过滤规则
object ClassOneNoOpFilter : JsonInclude.IncludeFilter() {
    override fun equals(value: Any?): Boolean = value === ClassOne.NO_OP
}

// 针对ClassTwo的单独过滤规则
object ClassTwoNoOpFilter : JsonInclude.IncludeFilter() {
    override fun equals(value: Any?): Boolean = value === ClassTwo.NO_OP
}

方案2:自定义序列化器(适合复杂场景)

如果你的ClassOne/ClassTwo有复杂的序列化逻辑,同时需要跳过NO_OP,可以给它们编写自定义序列化器,在序列化时直接跳过NO_OP实例:

class ClassOneSerializer : StdSerializer<ClassOne>(ClassOne::class.java) {
    override fun serialize(value: ClassOne, gen: JsonGenerator, provider: SerializerProvider) {
        if (value !== ClassOne.NO_OP) {
            // 在这里编写ClassOne的正常序列化逻辑
            gen.writeStartObject()
            gen.writeStringField("fieldA", value.fieldA)
            gen.writeIntField("fieldB", value.fieldB)
            gen.writeEndObject()
        }
        // 如果是NO_OP,什么都不写,结合@JsonInclude(Include.NON_NULL)的话,字段会被忽略
    }
}

// 同理编写ClassTwoSerializer

然后在你的类上注册序列化器:

@JsonSerialize(using = ClassOneSerializer::class)
class ClassOne {
    // ...类定义
    companion object {
        val NO_OP = ClassOne()
    }
}

关键注意事项

  • 一定要保证ClassOne.NO_OP和ClassTwo.NO_OP是单例对象(比如用object声明或者在companion object里定义为固定实例),这样===的引用相等判断才会准确,避免误过滤正常的业务实例。
  • 如果你的类重写了equals方法,可以把过滤条件里的===改成==,但单例的引用相等判断性能更好,也更安全。

内容的提问来源于stack exchange,提问作者metacubed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:44:12