I am using Jackson XML annotation to serialize/deserialize xml output of my spring boot APIs. This API is meant to provide legacy support. Because of that, it's required to have the exact same response structure as a new API as well. I encountered a peculiar situation for which I could not find any solution. I tried customSerilizer but that also doesn't seem to solve the problem.
I need to serialize A and B tags into pairs without any parent tags. The existing XML serilizes data in this format.
<Item>
<SNO>22656565</SNO>
<Weight>0.0</Weight>
<A>data1</A>
<B>foo1</B>
<A>data2</A>
<A>data3</A>
<B>foo3</B>
<A>data4</A>
<A>data5</A>
<A>data6</A>
<B>foo6</B>
</Item>
The java pojo look like this:
@Data
@JacksonXmlRootElement(localName = "Item")
@JsonPropertyOrder({"SNO", "Weight", "A", "B"})
public class Item {
@JacksonXmlProperty(localName = "SNO")
private String sNo;
@JacksonXmlProperty(localName = "Weight")
private Float weight;
@JacksonXmlProperty(localName = "A")
@JacksonXmlElementWrapper(useWrapping = false)
private List<String> aList;
@JacksonXmlProperty(localName = "B")
@JacksonXmlElementWrapper(useWrapping = false)
private List<String> bList;
}
Note: through a CustomSerializer I was able to read this data but serilization cannot be done. Whatever I try at the end all of A and B tags are grouped after serialization.
Could you please help in finding any solution to serialize this case? Thanks in advance.
It is possible to serialize your Item object with the alternate A and B tags in your xml file with a custom serializer, so if you use the provided Item class you can directly add a JsonSerialize annotation over your class and it will work fine with the constraint of the same size of the two not null lists like you have specified:
@JsonSerialize(using = ItemSerializer.class) //<-- here the new annotation
@Data
@JacksonXmlRootElement(localName = "Item")
@JsonPropertyOrder({"SNO", "Weight", "A", "B"})
public class Item {
@JacksonXmlProperty(localName = "SNO")
private String sNo;
@JacksonXmlProperty(localName = "Weight")
private Float weight;
@JacksonXmlProperty(localName = "A")
@JacksonXmlElementWrapper(useWrapping = false)
private List<String> aList;
@JacksonXmlProperty(localName = "B")
@JacksonXmlElementWrapper(useWrapping = false)
private List<String> bList;
}
So you can define a new class extending the StdSerializer providing the alternate writing of A and B tags for your lists:
public class ItemSerializer extends StdSerializer<Item> {
public ItemSerializer() {
super(Item.class);
}
@Override
public void serialize(Item value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeStartObject();
jgen.writeStringField("SNO", value.getSNo());
jgen.writeNumberField("Weight", value.getWeight());
List<String> aList = value.getAList();
for (int i = 0; i < aList.size(); ++i) {
jgen.writeStringField("A", aList.get(i));
jgen.writeStringField("B", value.getBList().get(i));
}
jgen.writeEndObject();
}
}
The expected result will be produced like below:
Item item = new Item();
item.setSNo("22656565");
item.setWeight(0.0f);
List<String> aList = List.of("data1", "data2", "data3");
item.setAList(aList);
List<String> bList = List.of("foo1", "foo2", "foo3");
item.setBList(bList);
String s = xmlMapper.writeValueAsString(item);
System.out.println(s);
Output:
<Item>
<SNO>22656565</SNO>
<Weight>0.0</Weight>
<A>data1</A>
<B>foo1</B>
<A>data2</A>
<B>foo2</B>
<A>data3</A>
<B>foo3</B>
</Item>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With