Jackson JSON在嵌套类的集合上给出了异常

Pie*_* dS 9 java serialization json jackson

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

public class MyClass {
   public class Nested {
      public String string;
      public Nested() {}
   }
   public Nested nestedVar;
}
Run Code Online (Sandbox Code Playgroud)

但在这一个:

public class MyClass {
   class Nested {
      public String string;
      public Nested() {}
   }
   public Nested nestedVar;
   public List<Nested> nestedList;
}
Run Code Online (Sandbox Code Playgroud)

反序列化时遇到此异常:

com.fasterxml.jackson.databind.JsonMappingException:找不到类型[simple type,class test.MyClass $ Nested]的合适构造函数:无法从JSON对象实例化(缺少默认构造函数或创建者,或者可能需要添加/启用类型信息) ?)at [来源:java.io.StringReader@26653222; line:1,column:48](通过引用链:test.MyClass ["nestedList"] - > java.util.ArrayList [0])

在第一种情况下,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);
}
Run Code Online (Sandbox Code Playgroud)

}

ara*_*nid 9

看起来非静态内部类的识别是在它们是包含bean的直接属性的情况下完成的(BeanDeserializerBase.java2.6.3中的第476行).因此,干预的集合解串器将超越它.自定义反序列化器可能是最简单的选择.

请注意,您仍然可以使用杰克逊阅读的特性Nested,只是实现它的建设自己,在自定义解串器反序列化的列表时使用Nested的对象.

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

    @JsonDeserialize(contentUsing = NestedDeserializer.class)
    public List<Nested> nestedList;
Run Code Online (Sandbox Code Playgroud)

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

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

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

例如:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)