在 Ktor 中指定要序列化为 JSON 的类字段

Posted

技术标签:

【中文标题】在 Ktor 中指定要序列化为 JSON 的类字段【英文标题】:Specify class fields to be serialized to JSON in Ktor 【发布时间】:2019-10-30 01:17:51 【问题描述】:

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

【问题讨论】:

像往常一样使用 gson api。非数据类应该可以正常工作。你也可以试试看。如果您需要更多帮助,请提供更具体的问题。 【参考方案1】:

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

1.使用瞬态

如果你用@Transient(Java 中的transient)标记一个字段,这将从序列化中排除:

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

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

这有一个巨大的缺点——java中的几乎每个框架都考虑@Transient,有时你不希望它被Gson序列化,但你可能希望将它持久化到数据库中(如果你会为两者使用相同的类)。为了解决这个问题,还有另一种选择,使用 @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 
  

shouldSkipField 中,当您不想序列化该字段时返回true,而当您想要序列化该字段时返回false。因为它接收一个FieldAttributes,所以你可以从字段中获取很多属性,例如名称和注释。这允许非常细粒度的控制。

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

【讨论】:

值得注意的是,ktor 将GsonBuilder 作为 gson 块中的接收者传递:install(ContentNegotiation) gson // Configure GsonBuilder here 所以我也可以只使用@SerializedName 指定JSON 序列化名称对吗? 是的。事实上,在 android 应用程序中我们总是这样做,因为变量的名称通常会被混淆,然后序列化的 json 会被完全破坏。我认为您不会在后端执行此操作,但如果您想要一个不同的名称,它仍然很方便。

以上是关于在 Ktor 中指定要序列化为 JSON 的类字段的主要内容,如果未能解决你的问题,请参考以下文章

如何在应用脚本高级服务中指定要在 Google DataStudio 中使用的数组字段?

为啥在 XSD 中定义为属性时,自动生成的类中的字段会序列化为元素?

将 JSON 包反序列化为具有自定义属性名称的类

将 Python namedtuple 序列化为 json

c#啥情况下json序列化会在字段中加空格

MySQL 无法在 FROM 多个表连接中指定要更新的目标表