java - Jackson JSON 给出了嵌套类集合的异常

标签 java json serialization jackson

Jackson JSON 序列化/反序列化这个类没有问题:

public class MyClass {
   public class Nested {
      public String string;
      public Nested() {}
   }
   public Nested nestedVar;
}

但是在这一个上:

public class MyClass {
   class Nested {
      public String string;
      public Nested() {}
   }
   public Nested nestedVar;
   public List<Nested> nestedList;
}

反序列化时出现异常:

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class test.MyClass$Nested]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?) at [Source: java.io.StringReader@26653222; line: 1, column: 48] (through reference chain: test.MyClass["nestedList"]->java.util.ArrayList[0])

在第一种情况下,Jackson 处理嵌套类的实例没有问题,但在第二种情况下则不然。

我必须编写自定义反序列化器吗?

测试代码(Jackson 2.6.3):

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

public class ATest {

   public static void main(String[] args) throws IOException {

      ObjectMapper mapper = new ObjectMapper();

      StringWriter sw = new StringWriter();

      MyClass myClass = new MyClass();

      MyClass.Nested nestedVar = myClass.new Nested();

      List<MyClass.Nested> nestedList = new ArrayList<>();

      nestedList.add(nestedVar);

      myClass.nestedList =nestedList;

      myClass.nestedVar = nestedVar;

      mapper.writeValue(sw, myClass);

      System.out.println(sw.toString());

      StringReader sr = new StringReader(sw.toString());

      MyClass z = mapper.readValue(sr, MyClass.class);
}

最佳答案

看起来非静态内部类的识别是在它们是其包含 bean 的属性的地方完成的(BeanDeserializerBase.java 2.6.3 中的第 476 行)。因此,一个干预的 Collection 反序列化器将超越它。自定义反序列化器可能是这里最简单的选择。

请注意,您仍然可以使用 Jackson 来读取 Nested 的属性,并自己实现它的构造,在反序列化列表时使用的自定义反序列化器 嵌套对象。

为此,请像这样注释列表:

    @JsonDeserialize(contentUsing = NestedDeserializer.class)
    public List<Nested> nestedList;

然后使用自定义反序列化器:

  1. 调用时查看解析上下文以查找包含的 MyClass 实例。

  2. 封装Nested 的默认/根级反序列化器,以将反序列化内容的工作委托(delegate)给。

例如:

public static final class NestedDeserializer extends StdDeserializer<MyClass.Nested>
    implements ResolvableDeserializer {
  private JsonDeserializer<Object> underlyingDeserializer;

  public NestedDeserializer() {
    super(MyClass.Nested.class);
  }

  @Override
  public void resolve(DeserializationContext ctxt) throws JsonMappingException {
    underlyingDeserializer = ctxt
        .findRootValueDeserializer(ctxt.getTypeFactory().constructType(MyClass.Nested.class));
  }

  @Override
  public Nested deserialize(JsonParser p, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {
    JsonStreamContext ourContext = p.getParsingContext();
    JsonStreamContext listContext = ourContext.getParent();
    JsonStreamContext containerContext = listContext.getParent();
    MyClass container = (MyClass) containerContext.getCurrentValue();
    MyClass.Nested value = container.new Nested();
    // note use of three-argument deserialize method to specify instance to populate
    underlyingDeserializer.deserialize(p, ctxt, value);
    return value;
  }
}

关于java - Jackson JSON 给出了嵌套类集合的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33707023/

相关文章:

c# - 防止 EF 5 生成属性

JavaScript从json获取数据到全局变量

javascript - 将 json 字符串转换为适合 esri.geometry.Multipoint 的字符串

javascript - 用于具有对象值的属性的 JSON.stringify 过滤器不起作用

java - 在 Java 中如何将 String 转换为 List<ClassName>?

Java Serialized - 序列化/反序列化是否安全?

java - effective Java Item1 - 用于创建对象的静态工厂方法

java - ActionScript 到 java (red5)

java - AbstractCreatorProcessor 类未找到错误

java - 导致构建错误的 Android Intent setType 和 addCategory 方法