Сериализация свойства с именем класса вместо имени свойства

Можно ли заставить Джексона и преобразователь XML сериализовать свойство, используя имя класса в качестве имени элемента вместо имени свойства?

т.е. данный:

package com.example.sometest;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;

public class Test2 {
    public static void main(String[] args) throws JsonProcessingException {
        XmlMapper mapper = new XmlMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.registerModule(new JaxbAnnotationModule());

        System.out.println(mapper.writeValueAsString(new A()));
    }
}

class A {
    public B getFoobar() {return new B();}
}

class B {
    public String getSomething() {return "something";}
}

Результат:

<A>
  <foobar>
    <something>something</something>
  </foobar>
</A>

Вместо этого я хотел бы, чтобы вывод был:

<A>
  <B>
    <something>something</something>
  </B>
</A>

Очевидно, что это должно применяться только к некоторым типам, иначе это повлияет и на строку, а это не то, что нам нужно здесь.

Это часть гораздо более крупного приложения, использующего xjc для создания классов XML, и в этом конкретном случае B также имеет супертипы, которые необходимо сериализовать с соответствующими именами классов в качестве имен элементов.

Изменить

Вот пример, в котором я хотел бы, чтобы окружающий элемент был фактическим именем класса, даже с наследованием:

public class Test2 {
    public static void main(String[] args) throws JsonProcessingException {
        XmlMapper mapper = new XmlMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.registerModule(new JaxbAnnotationModule());

        System.out.println(mapper.writeValueAsString(new A(new C())));
    }
}

class A {
    private final B object;

    A(B object) {this.object = object;}

    public B getFoobar() {return object;}
}

class B {
    public String getSomething() {return "something";}
}

class C extends B {
    public String getSomething() {return "other thing";}
}

Это произведет:

<A>
  <foobar>
    <something>other thing</something>
  </foobar>
</A>

Но должен произвести:

<A>
  <C>
    <something>other thing</something>
  </C>
</A>

Изменить2:

Это невозможно, как работает Джексон, поэтому это было решено с помощью специального сериализатора.


person Vetle    schedule 26.09.2019    source источник
comment
Можете ли вы реализовать собственный сериализатор для ваших типов B и т. д.? См. здесь или здесь. Затем используйте отражение, чтобы записать тип поля вместо имени поля.   -  person sfiss    schedule 26.09.2019
comment
Можете ли вы объяснить B also has supertypes that need to be serialized with their respective class names as element names as well. или лучше привести пример?   -  person Nikolai Shevchenko    schedule 26.09.2019
comment
@NikolayShevchenko готово   -  person Vetle    schedule 27.09.2019
comment
@sfiss это хорошее предложение, я рассмотрю его, спасибо   -  person Vetle    schedule 27.09.2019


Ответы (1)


Предоставление аннотации свойства XML в вашем классе позволит вам иметь метод getFoobar, который будет сериализован во что-то еще. https://mincong-h.github.io/2019/03/19/jackson-xml-mapper/

person Prathik Rajendran M    schedule 27.09.2019
comment
Да, но его нельзя изменить динамически в зависимости от типа значения свойства. Глядя на исходный код для XmlBeanSerializerBase, кажется, что его можно изменить на одно значение, но не изменять динамически. - person Vetle; 27.09.2019