Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在使用Jackson序列化java对象时维护子类型信息,而不使用包装器类_Java_Json_Serialization_Polymorphism_Jackson - Fatal编程技术网

在使用Jackson序列化java对象时维护子类型信息,而不使用包装器类

在使用Jackson序列化java对象时维护子类型信息,而不使用包装器类,java,json,serialization,polymorphism,jackson,Java,Json,Serialization,Polymorphism,Jackson,我试图使用Jackson在JSON文件和Java中包含两个子类的抽象类之间进行转换。理想情况下,我希望使用JSON,如下所示: 不带包装的Json文档 [ { "type" : "lion", "name" : "Simba", "endangered" : true, "action" : "running" }, { "type" : "elephant", "name" : "Dumbo", "endangered" : false, "table" : [

我试图使用Jackson在JSON文件和Java中包含两个子类的抽象类之间进行转换。理想情况下,我希望使用JSON,如下所示:

不带包装的Json文档

[ {
  "type" : "lion",
  "name" : "Simba",
  "endangered" : true,
  "action" : "running"
}, {
  "type" : "elephant",
  "name" : "Dumbo",
  "endangered" : false,
  "table" : [ 1.0, 2.0, 3.0 ]
} ]
{
  "animals" : [ {
    "type" : "lion",
    "name" : "Simba",
    "endangered" : true,
    "action" : "running"
  }, {
    "type" : "elephant",
    "name" : "Dumbo",
    "endangered" : false,
    "table" : [ 1.0, 2.0, 3.0 ]
  } ]
}
我已经注释了
Animal
抽象类,如图所示

我可以使用包装器对象成功地读/写它,但是生成的JSON文件将包含一个额外的
anives
对象

带包装的JSON文档

[ {
  "type" : "lion",
  "name" : "Simba",
  "endangered" : true,
  "action" : "running"
}, {
  "type" : "elephant",
  "name" : "Dumbo",
  "endangered" : false,
  "table" : [ 1.0, 2.0, 3.0 ]
} ]
{
  "animals" : [ {
    "type" : "lion",
    "name" : "Simba",
    "endangered" : true,
    "action" : "running"
  }, {
    "type" : "elephant",
    "name" : "Dumbo",
    "endangered" : false,
    "table" : [ 1.0, 2.0, 3.0 ]
  } ]
}
当我使用普通Java列表时,我可以在没有包装的情况下成功地读取Json文档,但是如果我尝试编写它,输出文件将如下所示:

// Test reading using array
Animal[] jsonArray = mapper.readValue(
        new FileInputStream(demoFile), Animal[].class);
System.out.println("Reading using array:\nObject: "
        + Arrays.toString(jsonArray));

// Test writing using array
outputJson = mapper.writeValueAsString(jsonArray);
System.out.println("Writing using array:\nJSON: " + outputJson);
output.json

[ {
  "name" : "Simba",
  "endangered" : true,
  "action" : "running"
}, {
  "name" : "Dumbo",
  "endangered" : false,
  "table" : [ 1.0, 2.0, 3.0 ]
} ]
Java代码

// Test reading using raw list
JavaType listType = mapper.getTypeFactory()
        .constructCollectionType(List.class, Animal.class);
List<Animal> jsonList = mapper.readValue(new FileInputStream(
        "demo.json"), listType);
jsonDocument = new File(outputFile);
// Test writing using raw list
mapper.writerWithDefaultPrettyPrinter().writeValue(jsonDocument,
        jsonList);

这里的问题是Java类型擦除,这意味着列表对象的标称类型是List。由于java.lang.Object没有@JsonTypeInfo,因此不会启用它

但您可以将Jackson配置为使用特定Java类型转换列表元素:

JavaType listJavaType = mapper.getTypeFactory().constructCollectionType(List.class, Animal.class);
String outputJson = mapper.writerWithType(listJavaType).writeValueAsString(myList);
修改您的代码:

公共静态void main(字符串[]args){

另一种解决方案: 您可以使用自定义TypeReference通知Jackson需要使用什么类来转换列表:

mapper.writerWithType(new TypeReference<List<Animal>>() {}).writeValueAsString(myList)
mapper.writerWithType(新类型引用(){}).writeValueAsString(myList)

该解决方案也可以工作,但我更喜欢主解决方案,因为它更干净,您不需要实例化抽象的“TypeReference”类…

谢谢,您是对的,我实际上发现它被列为“已知问题”在wiki中,.我最终使用了一个数组来避免创建类型引用,也许您想在解决方案中更新它,
Animal[]array=myList.toArray(新的Animal[myList.size());outputJson=mapper.writeValueAsString(数组);System.out.println(outputJson);
您使用
JavaType
而不是
TypeReference
的解决方案非常简单,因此我更新了我的问题:-)
mapper.writerWithType(new TypeReference<List<Animal>>() {}).writeValueAsString(myList)