【问题标题】:What is the purpose of using @field:SerializedName annotation instead of @SerializedName?使用@field:SerializedName 注解而不是@SerializedName 的目的是什么?
【发布时间】:2020-01-27 04:20:13
【问题描述】:

通常,我使用 @SerializedName 注释来映射 JSON 字段。但是,在 Google Architecture Component 示例项目中,我看到他们使用了 @field:SerializedName 注释,我无法找到任何地方来阅读使用该 @field 注释的目的。

我是 Kotlin 的新手,有人可以解释或分享要阅读的参考链接吗?谢谢。

@Entity(
    indices = [
        Index("id"),
        Index("owner_login")],
    primaryKeys = ["name", "owner_login"]
)
data class Repo(
    val id: Int,
    @field:SerializedName("name")
    val name: String,
    @field:SerializedName("full_name")
    val fullName: String,
    @field:SerializedName("description")
    val description: String?,
    @field:SerializedName("owner")
    @field:Embedded(prefix = "owner_")
    val owner: Owner,
    @field:SerializedName("stargazers_count")
    val stars: Int
) {...

【问题讨论】:

    标签: kotlin serialization annotations gson


    【解决方案1】:

    为了简化,假设您有:

    data class Repo(
        @field:SerializedName("name")
        var name: String
    )
    

    这是声明一个data class 并在primary constructor 中声明类'properties。 Kotlin 属性被编译成一个字段、getter 方法和——如果是可变的(即var)——一个 setter 方法。由于属性是在主构造函数中声明的,因此它也被编译为构造函数的参数。这一切意味着有许多位置可以在此上下文中放置注释:Kotlin 属性、支持字段、getter 方法、构造函数参数、setter 方法或 setter 参数。 field: 明确表明注释将应用于属性的backing field。来自the documentation

    #Annotation 使用站点目标

    当您注释属性或主要构造函数参数时,会从相应的 Kotlin 元素生成多个 Java 元素,因此在生成的 Java 字节码中有多个可能的注释位置。要指定应如何准确生成注释,请使用以下语法:

    class Example(@field:Ann val foo,    // annotate Java field
                  @get:Ann val bar,      // annotate Java getter
                  @param:Ann val quux)   // annotate Java constructor parameter
    

    可以使用相同的语法来注释整个文件。为此,请在文件的顶层、包指令之前或所有导入之前(如果文件在默认包中)放置一个带有目标 file 的注释:

    @file:JvmName("Foo")
    package org.jetbrains.demo
    

    如果您有多个注解具有相同的目标,您可以通过在目标后添加括号并将所有注解放在括号内来避免重复目标:

    class Example {
         @set:[Inject VisibleForTesting]
         var collaborator: Collaborator
    }
    

    支持的使用站点目标的完整列表是:

    • file;
    • property(带有此目标的注解对 Java 不可见);
    • field;
    • get(属性获取器);
    • set(属性设置器);
    • receiver(扩展函数或属性的接收方参数);
    • param(构造函数参数);
    • setparam(属性设置器参数);
    • delegate(存储委托属性的委托实例的字段)。

    要注释扩展函数的接收器参数,请使用以下语法:

    fun @receiver:Fancy String.myExtension() { ... }
    

    如果您不指定使用站点目标,则根据正在使用的注释的@Target 注释选择目标。如果有多个适用目标,则使用以下列表中的第一个适用目标:

    • param;
    • property;
    • field.

    【讨论】:

      【解决方案2】:

      这可能会有所帮助:from the kotlin docs

      当您注释属性或主要构造函数参数时,会从相应的 Kotlin 元素生成多个 Java 元素,因此在生成的 Java 字节码中有多个可能的注释位置。要指定应如何准确生成注释,请使用以下语法:

      class Example(@field:Ann val foo,    // annotate Java field
                    @get:Ann val bar,      // annotate Java getter
                    @param:Ann val quux)   // annotate Java constructor parameter
      

      【讨论】:

        【解决方案3】:

        虽然在这种情况下使用@field:SerializedName(...) 并非不正确,但是不必要的:无论是否添加@987654322,都会生成相同的字节码@ 因为无论哪种方式,只有私有支持字段将获得注释。我从未见过一个实际项目更喜欢@field:SerializedName 而不是@SerializedName,我认为Google 示例的使用对初学者来说是不必要的混乱。您应该随意忽略它。

        【讨论】:

          猜你喜欢
          • 2015-05-11
          • 2017-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-09
          • 2013-05-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多