如何在Kotlin中使用Jackson JsonSubTypes注释

cle*_*p6r 16 jackson kotlin

我正在尝试转换一些使用Jackson的@JsonSubTypes注释来管理多态的Java代码.

这是工作的Java代码:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Comment.class, name = "CommentNote"),
    @JsonSubTypes.Type(value = Photo.class, name = "PhotoNote"),
    @JsonSubTypes.Type(value = Document.class, name = "DocumentNote")
})
public abstract class Note implements Identifiable {
    [...]
Run Code Online (Sandbox Code Playgroud)

这是我认为相当于的Kotlin代码:

JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
JsonSubTypes(
    JsonSubTypes.Type(value = javaClass<Comment>(), name = "CommentNote"),
    JsonSubTypes.Type(value = javaClass<Photo>(), name = "PhotoNote"),
    JsonSubTypes.Type(value = javaClass<Document>(), name = "DocumentNote")
)
abstract class Note : Identifiable {
    [...]
Run Code Online (Sandbox Code Playgroud)

但是我在三个"JsonSubTypes.Type"行中得到以下错误:

Kotlin: An annotation parameter must be a compile-time constant
Kotlin: Annotation class cannot be instantiated
Run Code Online (Sandbox Code Playgroud)

任何的想法?

Gij*_*ijn 18

我相信这已经解决了,现在你可以像这样写:

import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo

@JsonTypeInfo(
   use = JsonTypeInfo.Id.NAME,
   include = JsonTypeInfo.As.PROPERTY,
   property = "type")
   @JsonSubTypes(
       JsonSubTypes.Type(value = Comment::class, name = "CommentNote"),
       JsonSubTypes.Type(value = Photo::class, name = "PhotoNote"),
       JsonSubTypes.Type(value = Document::class, name = "DocumentNote"))
interface Note
Run Code Online (Sandbox Code Playgroud)

请注意JsonSubTypes.Type中的类表示法

  • 编译器没有抱怨。当我使用 .java 属性时它会这样做。此解决方案适用于我的项目。 (2认同)

And*_*lav 9

原来这是编译器中的一个错误,感谢报告它.要解决此问题,您可以JsonSubTypes.Type无需限定地导入和使用它:

import org.codehaus.jackson.annotate.JsonSubTypes.Type

JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
JsonSubTypes(
    Type(value = javaClass<Comment>(), name = "CommentNote"),
    Type(value = javaClass<Photo>(), name = "PhotoNote"),
    Type(value = javaClass<Document>(), name = "DocumentNote")
)
abstract class Note : Identifiable {
    [...]
Run Code Online (Sandbox Code Playgroud)


Kem*_*giz 8

我知道这是一个老问题,但是如果有人仍在寻找使用 jackson 在 kotlin 中序列化/反序列化继承类的解决方案,我建议使用sealed类而不是使用@JsonSubTypes.

我还建议使用includeasEXISTING_PROPERTY并通过密封类内的 val 获取属性。否则,如果您在数组中添加组合的继承对象,jackson 将无法反序列化并抛出一个com.fasterxml.jackson.databind.exc.InvalidTypeIdException.

这是示例用法:

@JsonTypeInfo(
   use = JsonTypeInfo.Id.NAME,
   include = JsonTypeInfo.As.EXISTING_PROPERTY,
   property = "type")
sealed class Note{
    val type = this::class.java.simpleName
}
data class Document(val text: String, ...) : Note()
Run Code Online (Sandbox Code Playgroud)

这应该像一个魅力一样工作,包括在数组中使用此类!

这种方法的另一大优点是,您不需要手动设置任何内容。众所周知,手动操作很容易出错,因为如果您添加或删除子类、修改名称等,您可能会忘记添加/删除/修改。在这种方法中,您不需要手动雕刻子类型列表,也不需要手动给出类名的 json 表示形式。