一尘不染

杰克逊反序列化嵌套多态类型

json

我正在尝试使用Jakson反序列化嵌套的多态类型。意思是我的顶级类型引用了另一个多态类型,该类型最终由不是抽象的类扩展。这不起作用,并引发异常。

这是我要尝试做的简化示例。

package com.adfin;

import junit.framework.TestCase;
import org.codehaus.jackson.annotate.JsonSubTypes;
import org.codehaus.jackson.annotate.JsonTypeInfo;
import org.codehaus.jackson.map.ObjectMapper;

import java.io.IOException;

public class JaksonDouble extends TestCase {

  @JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "name"
  )
  @JsonSubTypes({
    @JsonSubTypes.Type(value = SecondLevel.class, name = "SECOND")
  })
  public static abstract class FirstLevel {
    public abstract String getTestValue();
  }

  @JsonTypeInfo(
    use = JsonTypeInfo.Id.CLASS,
    include = JsonTypeInfo.As.PROPERTY,
    property = "@class"
  )
  public static abstract class SecondLevel extends FirstLevel {

  }

  public static class FinalLevel extends SecondLevel {
    String test;
    @Override public String getTestValue() { return test; }
  }

  public void testDoubleAbstract() throws IOException {
    String testStr = "{ \"name\": \"SECOND\", \"@class\": \"com.adfin.JasksonDouble.FinalLevel\", \"test\": \"foo\"}";

    ObjectMapper mapper = new ObjectMapper();
    FirstLevel result = mapper.readValue(testStr, FirstLevel.class);
  }
}

我得到有关抽象类型的标准例外。

org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.adfin.JaksonDouble$SecondLevel, problem: abstract types can only be instantiated with additional type information at [Source: java.io.StringReader@f2a55aa; line: 1, column: 19]

让我解释一下我的用例。我有一个描述数据工作流程的Json文档。我在“一级”有一个抽象类型,描述了对单个值的操作。我派生了一堆不是抽象的类,它们实现了常见的操作(我用@JsonSubTypes注释了所有这些类)。

我有一个特殊的@JsonSubTypes,称为“ CUSTOM”。这是另一个抽象类,代表其他人(在常规jar之外)编写的自定义操作,并且他们可以使用“
@class”属性指定完全限定的类名称。看起来Jakson解析器从不读取第二个lavel类上的@JsonTypeInfo批注。

我该如何进行这项工作。或者至少如何使该用例起作用。


阅读 316

收藏
2020-07-27

共1个答案

一尘不染

您的定义搞砸了-您试图使用两个类型标识符,即类型名AND类。这没有任何意义。您应该选择一种或另一种方法,而不是两者都选。

如果选择Java类名称作为类型信息,则只需省略名称即可。另外,您只需要包含@JsonTypeInfofor FirstLevel;子类继承此定义。

如果您更喜欢使用逻辑类型名称,请删除class属性。您还需要指定带有注释的子类型列表,或者通过进行注册ObjectMapper

2020-07-27