Jackson将具有多态元素列表序列化为XML

ao218c7q  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(125)

我有一个Zoo类型,它有一个List<Animal>字段,它的元素是Animal子类的对象。当我用Jackson将一个Zoo对象序列化为XML时,我想为不同类型的元素生成不同的标记名。
例如:

abstract class Animal {}

@JacksonXmlRootElement(localName = "Dog")
class Dog extends Animal {}

@JacksonXmlRootElement(localName = "Cat")
class Cat extends Animal {}

@JacksonXmlRootElement(localName = "Zoo")
public class Zoo {

  @JacksonXmlProperty
  @JacksonXmlElementWrapper(useWrapping = false)
  List<Animal> animals = new ArrayList<>();
}

序列化Zoo示例。

public static void main(String[] args) throws JsonProcessingException {
  Zoo zoo = new Zoo();
  zoo.animals.add(new Dog());
  zoo.animals.add(new Cat());
  zoo.animals.add(new Dog());
  String xml = new XmlMapper().writerWithDefaultPrettyPrinter()
      .writeValueAsString(zoo);
  System.out.println(xml);
}

我期望得到:

<Zoo>
  <Dog/>
  <Cat/>
  <Dog/>
</Zoo>

实际输出:

<Zoo>
  <animals/>
  <animals/>
  <animals/>
</Zoo>
5ktev3wc

5ktev3wc1#

使用自定义的序列化程序可以获得预期的结果,但是您失去了使用JsonTypeInfo的所有优点,并且您还必须编写自定义的反序列化程序。无论如何,您可以定义三个简单的类,如下所示:

public abstract class Animal {}
public class Dog extends Animal {}

@JsonSerialize(using = ZooSerializer.class)
public class Zoo {
  List<Animal> animals = new ArrayList<>();
}

然后,您必须编写自定义的ZooSerializer序列化程序,该程序将生成自定义的xml:

public class ZooSerializer extends StdSerializer<Zoo> {

    public ZooSerializer(Class<Zoo> t) {
        super(t);
    }
    
    public ZooSerializer() {
        this(null);
    }

    @Override
    public void serialize(Zoo zoo, JsonGenerator jg, SerializerProvider sp) throws IOException {
        jg.writeStartObject();
        for (Animal animal: zoo.animals) {
            jg.writeNullField(animal.getClass().getSimpleName());
        }
        jg.writeEndObject();
    }
}

这将产生预期的结果,但代价是失去了所有优点,因为自动序列化和反序列化可以通过JsonTypeInfoJsonSubTypes注解在两个类上获得:

Zoo zoo = new Zoo();
zoo.animals.add(new Dog());
zoo.animals.add(new Dog());
/* the str content obtained by the serialization of zoo
Zoo>
  <Dog/>
  <Dog/>
</Zoo>
*/
String str = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(zoo);

相关问题