【问题标题】:Usage of Jackson @JsonProperty annotation for kotlin data classes对 kotlin 数据类使用 Jackson @JsonProperty 注释
【发布时间】:2018-06-07 12:09:23
【问题描述】:

科特林 1.2.10 jackson-module-kotlin:2.9.0

我在 kotlin 中有以下数据类:

data class CurrencyInfo(
        @JsonProperty("currency_info") var currencyInfo: CurrencyInfoItem?
)

@JsonInclude(JsonInclude.Include.NON_NULL)
data class CurrencyInfoItem(
        @JsonProperty("iso_4217") var iso4217: String?,
        @JsonProperty("name") var name: String?,
        @JsonProperty("name_major") var nameMajor: String?,
        @JsonProperty("name_minor") var nameMinor: String?,
        @JsonProperty("i_ma_currency") var iMaCurrency: Int?,
        @JsonProperty("i_merchant_account") var iMerchantAccount: Int?,
        @JsonProperty("i_x_rate_source") var iXRateSource: Int?,
        @JsonProperty("base_units") var baseUnits: Double?,
        @JsonProperty("min_allowed_payment") var minAllowedPayment: Int?,
        @JsonProperty("decimal_digits") var decimalDigits: Int?,
        @JsonProperty("is_used") var isUsed: Boolean?
)

当我尝试反序列化这个数据类时,我得到以下信息:

{"currency_info":{"iso_4217":"CAD","name":"Canadian Dollar","imerchantAccount":0,"ixrateSource":2}}

如您所见,最后两个选项被错误地反序列化。 这个问题可以通过直接向getter @get:JsonProperty 添加注解来解决。但是,根据杰克逊文档,@JsonProperty 应该分配给 getters/setters/fields

所以,我想问是否有一种可靠的方法可以在 kotlin 中为 jackson 注释属性以进行正确的序列化/反序列化(此外,我所有的数据类都是自动生成的,因此很难创建一些两/三行注释,分别用于 getter 和 setter)

否则,这个问题可以通过一些杰克逊设置来解决吗?

根据下面的答案,以下对我有用

private val mapper = ObjectMapper().registerKotlinModule()
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE)

【问题讨论】:

  • 您只需要 .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE)。问题取决于对“is”getter 的具体处理

标签: java json jackson kotlin deserialization


【解决方案1】:

@JsonProperty 代码中的注释都放在数据类中的私有字段上,默认情况下,Jackson 不会扫描私有字段以查找注释。您必须通过添加@JsonAutoDetect 注释来指示它不这样做:

@JsonAutoDetect(fieldVisibility = Visibility.ANY)
data class CurrencyInfo(
    @JsonProperty("currency_info") var currencyInfo: CurrencyInfoItem?
)

或者您也可以在访问器方法上移动您的注释:

data class CurrencyInfo(
    @get:JsonProperty("currency_info") var currencyInfo: CurrencyInfoItem?
)

【讨论】:

  • 谢谢,我设置了全局可见性修饰符
  • 我有jackson-annotations-2.9.0,但没有PRIVATE 选项。我尝试使用ANY,但该属性仍然被忽略。 View Source code
  • 使用@param:JsonProperty("")answer down below 也很重要,如果你试图复制它以获得值时不会发生的事情,即在构造时发生的自定义Json Deserializers .
  • 这些都不适合我
【解决方案2】:

你可以这样做:

data class CurrencyInfo @JsonCreator constructor (
        @param:JsonProperty("currency_info") 
        @get:JsonProperty("currency_info")
        val currencyInfo: CurrencyInfoItem?
)

上面的代码翻译成java:

public final class CurrencyInfo {
   @Nullable
   private final String currencyInfo;

   @JsonProperty("currency_info")
   @Nullable
   public final String getCurrencyInfo() {
      return this.currencyInfo;
   }

   @JsonCreator
   public CurrencyInfo(@JsonProperty("currency_info") @Nullable String currencyInfo) {
      this.currencyInfo = currencyInfo;
   }
}

接受答案的代码转换为 java 如下:

首先(不是纯不可变的):

@JsonAutoDetect(
   fieldVisibility = Visibility.ANY
)
public final class CurrencyInfo {
   @Nullable
   private String currencyInfo;

   @Nullable
   public final String getCurrencyInfo() {
      return this.currencyInfo;
   }

   public final void setCurrencyInfo(@Nullable String var1) {
      this.currencyInfo = var1;
   }

   public CurrencyInfo(@JsonProperty("currency_info") @Nullable String currencyInfo) {
      this.currencyInfo = currencyInfo;
   }
}

第二个(可能反序列化有问题):

public final class CurrencyInfo {
   @Nullable
   private final String currencyInfo;

   @JsonProperty("currency_info")
   @Nullable
   public final String getCurrencyInfo() {
      return this.currencyInfo;
   }

   public CurrencyInfo(@Nullable String currencyInfo) {
      this.currencyInfo = currencyInfo;
   }
}

【讨论】:

    【解决方案3】:

    您可以添加jackson-module-kotlin (https://github.com/FasterXML/jackson-module-kotlin) 并将 kotlin 模块注册到 jackson:

    val mapper = ObjectMapper().registerModule(KotlinModule())
    

    然后它(和许多其他东西)会自动运行。

    【讨论】:

    • 从一开始就使用它。您甚至可以检查问题帖子中的初始化。
    • @Mike 是的,我错过了那个。然而,它为我完成了这项工作。
    • 到目前为止,这是最好的答案:注册此模块不仅可以解决问题而无需输入 @get: 或使用其他调整,而且还可以提高 KotlinJackson 的整体互操作性。
    【解决方案4】:

    你可以通过调用setPropertyNamingStrategy(...)方法从jackson库中配置ObjectMapper

    使用PropertyNamingStrategy.SNAKE_CASE 应该可以解决您的问题

    另请参阅此处的其他可用策略:PropertyNamingStrategy

    【讨论】:

    • 谢谢,这是个好主意,我试过了。但是默认的 SNAKE_CASE 翻译的实现很差。很多字段解析不正确。比如iso4217 -> 没有翻译成iso_4217,iXRateSource -> i_x_rate_source 等等
    【解决方案5】:

    Kotlin 不支持@param 和@get 注解作为一个注解,所以我们只好写这样的代码:

    data class User(
        @param:JsonProperty("id") @get:JsonProperty("id") val id: Int,
        @param:JsonProperty("name") @get:JsonProperty("name") val name: String
    )
    

    您可以在这里告诉 JetBrain 人员支持此功能并允许:

    data class User(
        @JsonProperty("id") val id: Int,
        @JsonProperty("name") val name: String
    )
    

    https://youtrack.jetbrains.com/issue/KT-11005

    【讨论】:

      【解决方案6】:

      我今天遇到了这个问题,我所做的就是在我的 ObjectMapper() 中注册 KotlinModule()。波纹管跟随一个例子。

      @Bean fun objectMapper = ObjectMapper().registreModule(KotlinModule())
      

      上面是一个虚拟的objectMapper,我相信你应该把其他配置放在你的objectMapper中,比如序列化器等等

      【讨论】:

        【解决方案7】:

        此问题已解决

        https://github.com/FasterXML/jackson-module-kotlin/issues/237

        或者你也可以使用

        data class SignRequest    
            @param:JsonProperty("estamp_request")
            @get:JsonProperty("estamp_request")
            val eStamp: EstampRequest?
        }
        
        data class EstampRequest(
            val tags: Map<String,Int>
        )
        

        【讨论】:

          猜你喜欢
          • 2018-04-19
          • 2019-11-09
          • 1970-01-01
          • 2018-05-20
          • 2018-01-23
          • 2012-12-14
          • 1970-01-01
          • 1970-01-01
          • 2014-06-02
          相关资源
          最近更新 更多