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

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



}


呼如林
浏览 224回答 1
1回答

RISEBY

解决这个问题有两个因素。第一:如果没有指定 @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 的自动检测
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java