0

Is it possible to make Jackson and the XML mapper to serialize a property using the class name as the element name instead of the property name?

I.e. given:

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";}
}

The result is:

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

Instead, I would like the output to be:

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

Obviously this would have to only apply to some types, or it would affect the string as well, which is not what we want here.

This is part of a much larger application, using xjc to generate XML classes, and in this particular case B also has supertypes that need to be serialized with their respective class names as element names as well.

Edit

Here's an example where I would like the surrounding element to be the actual class name, even with inheritance:

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";}
}

This will produce:

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

But should produce:

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

Edit2:

This is not possible the way Jackson works, so it was solved using a custom serializer.

Vetle
  • 3,287
  • 2
  • 27
  • 28
  • 1
    Can you implement a custom serializer for your types `B` etc.? See [here](https://stackoverflow.com/questions/12046786/jackson-json-custom-serialization-for-certain-fields) or [here](https://stackoverflow.com/questions/58076716/custom-annotation-based-ignore-field-from-serialisation/58077671#58077671). Then use reflection to write the field type instead of field name. – sfiss Sep 26 '19 at 15:44
  • Can you explain `B also has supertypes that need to be serialized with their respective class names as element names as well.` or better give example? – Nikolai Shevchenko Sep 26 '19 at 17:06
  • @NikolayShevchenko done – Vetle Sep 27 '19 at 06:02
  • @sfiss that's a good suggestion, I'll look into it, thank you – Vetle Sep 27 '19 at 06:03

1 Answers1

0

Providing XML property annotation on your class will allow you to have a method getFoobar that is serialized into something else. https://mincong-h.github.io/2019/03/19/jackson-xml-mapper/

Prathik Rajendran M
  • 1,152
  • 8
  • 21
  • Yes, but it can't be changed dynamically based on the property value type. Looking at the source code for `XmlBeanSerializerBase`, it seems that it can be change to a single value, but not be dynamically changing. – Vetle Sep 27 '19 at 09:23