Reputation: 77
I am updating a POJO
that we map to XML
and the only difference is that someone wants both the old XML
and some new, and with the only difference being the root Wrapper name (all the same fields), e.g. currently the root Xml Tag is set to ExistingName
and they want a new value like BrandNewName
with all the same fields. And still get the old. Is there a way to just flip this in the POJO
?
I figured I could do it with some inheritance and a base class with two implementations, but seemed overkill
I know I can set the root tag with @JacksonXmlRootElement
, but is it possible to set it to a variable name.
@JacksonXmlRootElement(localName = 'ExistingName')
class MyPojo {
String commonVar1
String commonVar1
String commonVar1
}
Upvotes: 3
Views: 5026
Reputation: 77
I ended up finding Get Jackson XMLMapper to set root element name in code and just setting using
XmlMapper mapper = new XmlMapper();
.writer()
.withRootName(myFieldName)
.writeValueAsString(myPojo ));
Upvotes: 3
Reputation: 38625
You can use MixIn
feature and dynamically declare name for root type:
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
public class XmlMapperApp {
public static void main(String[] args) throws Exception {
XmlMapper xmlMapperOld = new XmlMapper();
xmlMapperOld.addMixIn(MyPojo.class, MyPojoExistingNameMinIn.class);
XmlMapper xmlMapperNew = new XmlMapper();
xmlMapperNew.addMixIn(MyPojo.class, MyPojoBranNewNameMinIn.class);
System.out.println(xmlMapperOld.writeValueAsString(new MyPojo()));
System.out.println(xmlMapperNew.writeValueAsString(new MyPojo()));
}
}
@JacksonXmlRootElement(localName = "ExistingName")
interface MyPojoExistingNameMinIn {
}
@JacksonXmlRootElement(localName = "BrandNewName")
interface MyPojoBranNewNameMinIn {
}
Above code prints:
<ExistingName><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName>
<BrandNewName><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></BrandNewName>
But we can also create an extra POJO
to store object and name we want to assign during serialisation process. To make it work we need to implement custom JsonSerializer
and implement that behaviour. Example solution could look like below:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.util.NameTransformer;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.Objects;
public class XmlMapperApp {
public static void main(String[] args) throws Exception {
XmlMapper xmlMapper = new XmlMapper();
for (char c = 65; c < 70; c++) {
System.out.println(xmlMapper.writeValueAsString(new PersistAs("ExistingName_" + c, new MyPojo())));
}
}
}
class PersistAsJsonSerializer extends JsonSerializer<PersistAs> {
@Override
public void serialize(PersistAs value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
ToXmlGenerator xmlGen = (ToXmlGenerator) gen;
// set desired name
xmlGen.setNextName(new QName(value.getName()));
xmlGen.writeStartObject();
// serialise fields
XmlBeanSerializer serializer = (XmlBeanSerializer) serializers.findValueSerializer(value.getValue().getClass());
JsonSerializer<Object> unwrappingSerializer = serializer.unwrappingSerializer(NameTransformer.NOP);
unwrappingSerializer.serialize(value.getValue(), gen, serializers);
// end of root
gen.writeEndObject();
}
}
@JsonSerialize(using = PersistAsJsonSerializer.class)
class PersistAs {
private final String name;
private final Object value;
public PersistAs(String name, Object value) {
this.name = Objects.requireNonNull(name);
this.value = Objects.requireNonNull(value);
}
public String getName() {
return name;
}
public Object getValue() {
return value;
}
@Override
public String toString() {
return "PersistAs{" +
"name='" + name + '\'' +
", value=" + value +
'}';
}
}
Above code prints:
<ExistingName_A><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_A>
<ExistingName_B><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_B>
<ExistingName_C><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_C>
<ExistingName_D><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_D>
<ExistingName_E><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_E>
Upvotes: 1