【问题标题】:Exclude non-null properties when serializing a Kotlin data class序列化 Kotlin 数据类时排除非空属性
【发布时间】:2026-02-16 01:20:04
【问题描述】:

我经常会在 Kotlin 中创建一个内部用于数据模型的数据类。示例:

data class MyDataModel(
    var id: String? = null,
    var ownerId: String,
    var name: String,
    var isPrivate: Boolean = false,
)

我经常需要将这些类序列化为 JSON。问题是某些类属性不可为空,并且在某些情况下我需要在序列化中排除这些字段。我还没有找到一种干净简单的方法来做到这一点。我目前使用的解决方案是不使用不可为空的属性,然后将那些我不想序列化的属性设置为空。

还有其他方法吗?

【问题讨论】:

  • 你用什么来序列化/反序列化?有多种方法取决于此。
  • Gson。 Kotlin 也有自己的序列化,但现阶段确实还不成熟。我不需要反序列化。只是序列化。
  • 在这种情况下,我建议使用此处提供的一种方式baeldung.com/gson-exclude-fields-serialization
  • 我知道该解决方案。只是为了获得空序列化而过于复杂。
  • 是的,它适用于 kotlin,是的,您只需要添加 @JsonIgnore。我们使用 jackson 是因为它带有 spring(我们几乎所有的服务都在 kotlin 中)。您将需要使用 jackson-module-kotlin(它位于主 maven 存储库中)。问题是,我不知道您的其余代码是否知道杰克逊是否在各个方面都比 gson 更好,但至少在这种特殊情况下,它要容易得多。你可以在这里看到 7 号 baeldung.com/jackson-field-serializable-deserializable-or-not(顺便说一句,我不隶属于 baeldung)

标签: kotlin


【解决方案1】:

使用kotlinx.serialization的解决方案:

  1. 定义类,包括你要序列化的所有字段,标记为@Serializable
@Serializable
open class MyDataModelSerializable(
    open var id: String? = null
)
  1. 将您的数据类设为其子类型:
data class MyDataModel(
    var ownerId: String,
    var name: String,
    var isPrivate: Boolean = false,
    override var id: String? = null
) : MyDataModelSerializable(id)
  1. 使用MyDataModelSerializable 的序列化程序序列化MyDataModel 类的实例:
val s = serializer<MyDataModelSerializable>()
println(Json.encodeToString(s, MyDataModel(ownerId = "1", name = "2", id = "3", isPrivate = true))) //{"id":"3"}
println(Json.encodeToString(s, MyDataModel(ownerId = "1", name = "2", isPrivate = true))) //{}
println(Json{encodeDefaults = true}.encodeToString(s, MyDataModel(ownerId = "1", name = "2"))) //{"id":null}

【讨论】:

  • 但这会序列化整个类。 Gson 没有做任何事情。此外,您为第一项显示的输出仅显示 id,但 name 和 ownerId 不为空,也应序列化。
  • 但这是您最初的要求 - 不序列化不可为空的字段。也许你把他们弄糊涂了?可以为空的引用是可以为空的引用(如String?),不可为空的 - 是那些不能为空的引用(如String)。
  • 如果你需要相反 - 排除可空类型,它更容易,你不需要任何辅助类,只需将原始数据类标记为@Serializable,将可空字段标记为@987654332 @
  • 此外,序列化库不编码默认值,因此,如果您不希望出现具有 null 值的属性,请将其作为默认值(例如在您的示例中,@987654334 @) 并且仅当它设置为非空值时才会包含在内。我同意虽然您并不清楚您想要什么,但可能值得阅读指南介绍,看看它是否适合您想要做的事情:github.com/Kotlin/kotlinx.serialization/blob/master/docs/…