【问题标题】:Jackson with Kotlin: how to serialize only annotated propertiesJackson 与 Kotlin:如何仅序列化带注释的属性
【发布时间】:2020-08-01 06:00:15
【问题描述】:

我正在尝试在我现有的 Java 项目中开始使用 Kotlin,但 Jackson 没有在我的 Kotlin 对象中检测到 @JsonProperty(而它与 Java 对象完美配合)。

有什么方法可以配置 Jackson 以使其在 Kotlin 上像在 Java 上一样工作?

这是 Java 类:

public class TestJavaObj {
    @JsonProperty
    private String includeMe;
    private String dontIncludeMe;

    public TestJavaObj(String includeMe, String dontIncludeMe) {
        this.includeMe = includeMe;
        this.dontIncludeMe = dontIncludeMe;
    }
}

还有 Kotlin 类:

class TestKotlinObj(
    @JsonProperty val includeMe: String,
    val dontIncludeMe : String?
)

这里是测试代码:

public static void main(String[] args) throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper()
            .registerModule(new KotlinModule()) //jackson-module-kotlin
            .configure(MapperFeature.AUTO_DETECT_GETTERS, false)
            .configure(MapperFeature.AUTO_DETECT_CREATORS, false)
            .configure(MapperFeature.AUTO_DETECT_FIELDS, false)
            .configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false)
            .configure(MapperFeature.AUTO_DETECT_SETTERS, false);

    TestJavaObj javaObj = new TestJavaObj("hello", "world");
    TestKotlinObj kotlinObj = new TestKotlinObj("hello", "world");

    System.out.println("Expected: " + mapper.writeValueAsString(javaObj));
    System.out.println("Got: " + mapper.writeValueAsString(kotlinObj));
}

这是输出:

Expected: {"includeMe":"hello"}
Got: {}

我的 gradle 文件中的版本号:

kotlin_version = '1.3.72'
...
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version" 
...
apply plugin: 'kotlin'
...
compile('com.fasterxml.jackson.core:jackson-annotations:2.10.3')
compile('com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8')
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

【问题讨论】:

  • @unzila 似乎是关于向 bean 类添加自定义序列化程序。我想做的是让 Kotlin 类序列化以与 Java 序列化相同的方式工作。

标签: java kotlin serialization jackson


【解决方案1】:

指定注解use-site target:

class TestKotlinObj(
        @get:JsonProperty val includeMe: String,
        val dontIncludeMe : String
)

结果:

Expected: {"includeMe":"hello"}
Got: {"includeMe":"hello"}

背景

翻译成Java字节码的类只有一个注解的构造函数参数:

public final class TestKotlinObj {
   @NotNull // no annotation here
   private final String includeMe;
   @NotNull
   private final String dontIncludeMe;

   @NotNull // nor here
   public final String getIncludeMe() {
      return this.includeMe;
   }

   @NotNull
   public final String getDontIncludeMe() {
      return this.dontIncludeMe;
   }
                     // but here
                     // vvvv 
   public TestKotlinObj(@JsonProperty @NotNull String includeMe, @NotNull String dontIncludeMe) {
      Intrinsics.checkParameterIsNotNull(includeMe, "includeMe");
      Intrinsics.checkParameterIsNotNull(dontIncludeMe, "dontIncludeMe");
      super();
      this.includeMe = includeMe;
      this.dontIncludeMe = dontIncludeMe;
   }
}

序列化对象时没有考虑到这一点。

查看相关问题: Kotlin data class Jackson @JsonProperty not honored

【讨论】:

  • 谢谢,这非常有帮助。出于好奇,是否有一种简单的方法可以查看 Kotlin 类的 Java 等价物是什么?或者你只是知道它是这样工作的?
  • 没问题,当然。如果您使用 Intellij IDEA,您可以:打开文件,转到工具 -> Kotlin -> 显示 Kotlin 字节码 -> 反编译。另见this问题
【解决方案2】:

尝试将 Kotlin 类更改为:

class TestKotlinObj {
    @JsonProperty
    val includeMe: String;
    val dontIncludeMe : String;

    constructor(includeMe: String, dontIncludeMe: String) {
      this.includeMe = includeMe;
      this.dontIncludeMe = dontIncludeMe;
    }
}

可能您当前拥有的 Kotlin 类与 java 中的 this 等价(这显然行不通):

public class TestJavaObj {
    public String includeMe;
    public String dontIncludeMe;

    public TestJavaObj(@JsonProperty String includeMe, String dontIncludeMe) {
        this.includeMe = includeMe;
        this.dontIncludeMe = dontIncludeMe;
    }
}

【讨论】:

    猜你喜欢
    • 2014-11-11
    • 2015-01-06
    • 2014-11-28
    • 1970-01-01
    • 2019-07-24
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多