为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 Jackson 会为以 is 开头的 Kotlin 布尔型 val 抛出

为什么 Jackson 会为以 is 开头的 Kotlin 布尔型 val 抛出

呼如林 2023-04-19 15:39:17
class JacksonError(    val x: String,    val isSomething: Boolean)因错误而失败com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "something" (class ch.cypherk.blah.JacksonError), not marked as ignorable (2 known properties: "x", "isSomething"])而没有这样的问题class NoJacksonError(    val x: String,    val something: Boolean)我的第一直觉是 Jackson 不理解isXY-getters 而它只需要getters 开始get。然而,有趣的是,也没有问题class AlsoNoJacksonError (    val x: String,    var isSomething: Boolean)这意味着我不知道发生了什么。JacksonError被编译为public final class ch.cypherk.blah.JacksonError {  public final java.lang.String getX();    Code:       0: aload_0       1: getfield      #11                 // Field x:Ljava/lang/String;       4: areturn  public final boolean isSomething();    Code:       0: aload_0       1: getfield      #18                 // Field isSomething:Z       4: ireturn  public ch.cypherk.blah.JacksonError(java.lang.String, boolean);    Code:       0: aload_1       1: ldc           #21                 // String x       3: invokestatic  #27                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V       6: aload_0       7: invokespecial #30                 // Method java/lang/Object."<init>":()V      10: aload_0      11: aload_1      12: putfield      #11                 // Field x:Ljava/lang/String;      15: aload_0      16: iload_2      17: putfield      #18                 // Field isSomething:Z      20: return}NoJacksonError被编译为public final class ch.cypherk.blah.NoJacksonError {  public final java.lang.String getX();    Code:       0: aload_0       1: getfield      #11                 // Field x:Ljava/lang/String;       4: areturn  public final boolean getSomething();    Code:       0: aload_0       1: getfield      #19                 // Field something:Z       4: ireturn}
查看完整描述

1 回答

?
RISEBY

TA贡献1856条经验 获得超5个赞

解决这个问题有两个因素。
第一:如果没有指定 @JsonProperty 字段,
Jackson 默认使用 Java bean 命名约定来暗示 json 字段名称(对于布尔字段,其 getter/setter 的命名约定是什么? )。我测试了代码,序列化适用于 JacksonError 类,因为有一个 getter 符合 bean 访问器的 Java 命名标准。然而,在反序列化时,它看起来是通过名称“setSomething()”访问一个 getter。如果您观察到,具有 setSomething 方法的类不会出现反序列化错误。

第二:没有为 JacksonError 类生成 setSomething() 方法的原因是因为它是一个 val 字段并且它不生成 setter(val 字段是不可变的并且仅在构造函数中初始化,因此没有 setter)。就像@Erwin Bolwidt 建议的那样,您可以将以下属性设置为对象映射器以包含 jackson 的 kotlin 模块

 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)

ObjectMapper().registerKotlinModule :这注册了有助于序列化/反序列化 kotlin 类的模块。

setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) :使所有字段可序列化,包括私有字段(在您的情况下为 val 字段)

        .setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE)  :  Makes sure any static / factory constructors are not autodetected

        .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
        .setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
        .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE) :

所有这些道具都通知对象映射器忽略任何 getters/setters 和 boolean setters 的自动检测


查看完整回答
反对 回复 2023-04-19
  • 1 回答
  • 0 关注
  • 223 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信