在 Ktor 中指定 class 字段序列化为 JSON

Specify class fields to be serialized to JSON in Ktor

Serving JSON content in Ktor as described in HTTP API - Quick Start - Ktor,如示例所示,适用于常见集合(列表、地图等)和数据 classes。但是,如果我想序列化一个 class 而不是数据 class 并且有我想排除的字段,我该如何指定要序列化的字段及其序列化名称?假设我使用的是Gson,我可以像直接使用Gson序列化一个class对象一样吗?

据我所知,使用 Gson,您有几个选择。

1.使用瞬态

如果您用 @Transient 标记字段(Java 中的 transient),这将被排除在序列化之外:

data class Foo(
    @Transient val a: Int,
    val b: Int)

这里,b会被序列化,a不会。

这带来了一个巨大的缺点——几乎 java 中的每个框架都考虑到了 @Transient,有时你不希望它被 Gson 序列化,但你可能想要坚持它例如到数据库(如果你对两者使用相同的class)。为了解决这个问题,还有另一种选择,使用 @Expose.

2。使用暴露

您需要使用构建器创建 gson 实例:

val gson = GsonBuilder()
    .excludeFieldsWithoutExposeAnnotation()
    .create();

现在,没有 @Expose 的字段将不会被序列化:

data class Foo(
    val a: Int,
    @Expose val b: Int)

同样,a 不会被序列化,但 b 会。

3。使用排除策略

更高级的方法是使用排除策略。这允许对字段进行大量自省。从自定义注释到字段名称或类型。

同样,您需要使用构建器创建一个 gson

val gson = GsonBuilder()
    .addSerializationExclusionStrategy(strategyInstance)
    .create();

然后您定义一个策略,例如:

object : ExclusionStrategy() {
  override fun shouldSkipField(field: FieldAttributes): Boolean {
  }

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

inside shouldSkipField 你 return true 当你不想序列化字段时 false 当你这样做时。因为它接收到一个 FieldAttributes ,所以你可以从该字段中获取很多属性,例如名称和注释。这允许非常 fine-grained 控制。

最后,您也可以为反序列化设置此策略,并且为 - addDeserializationExclusionStrategysetExclusionStrategies