1

Using Jackson to serialize a simple type hierarchy:

static class Base {
    @JsonProperty
    private final int foo = 42;
}

static class Derived extends Base {
    @JsonProperty
    private final int bar = 39;
}

Using the Jackson XmlMapper I'm getting the following output:

<Derived>
  <foo>42</foo>
  <bar>39</bar>
</Derived>

What I'd really like to get is XML containing the base type:

<Derived>
  <Base>
    <foo>42</foo>
  </Base>
  <bar>39</bar>
</Derived>

I browsed the Jackson API, especially the type annotations and SerializationFeature, but couldn't figure out how to achieve this.

Any ideas?

I'm looking for a generic approach since I'm dealing with several hundred classes in deeply nested hierarchies.


Update

At least I figured out how to do this using XStream:

public class TypeHierarchyConverter implements Converter {

    @Override
    public boolean canConvert(@SuppressWarnings("rawtypes") final Class clazz) {
        return Base.class.isAssignableFrom(clazz);
    }

    @Override
    public void marshal(final Object value, final HierarchicalStreamWriter writer,
            final MarshallingContext context) {
        try {
            enumerateFields(value, writer, context);
        } catch (final IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
        return null;
    }

    private void enumerateFields(final Object value, final HierarchicalStreamWriter writer,
            final MarshallingContext context) throws IllegalAccessException {
        enumerateFields(value, writer, context, value.getClass(), false);
    }

    private void enumerateFields(final Object value, final HierarchicalStreamWriter writer,
            final MarshallingContext context, final Class<?> c, final boolean nest) throws IllegalAccessException {
        final String name = c.getSimpleName();
        if (nest) {
            writer.startNode(name);
        }
        final Class<?> superclass = c.getSuperclass();
        if (!Object.class.equals(superclass)) {
            enumerateFields(value, writer, context, superclass, true);
        }
        final Field[] fields = c.getDeclaredFields();
        for (final Field f : fields) {
            f.setAccessible(true);
            writer.startNode(f.getName());
            context.convertAnother(f.get(value));
            writer.endNode();
            f.setAccessible(false);
        }
        if (nest) {
            writer.endNode();
        }
    }

}

Still no idea hot to do this with Jackson. :(

leftbit
  • 848
  • 1
  • 7
  • 18
  • You need to implement custom `JsonSerializer` for your class. Take a look at [Coverting a Java HashMap to XMl using Jackson library](https://stackoverflow.com/a/59373684/51591), [Jackson add wrapper based on field values](https://stackoverflow.com/a/58275241/51591) – Michał Ziober Jul 01 '21 at 10:46

0 Answers0