Reputation: 3520
I have a simple Java program that marshalls my Java object to XML. It's working fine but the only problem is that during the marshalling of List<String>
it adds an additional <name>
which I do not want.
I have a field in my Employee.class
which is Object
and it can be either a String
or List<String>
so to Jakarta/JAXB marshall
field I am using my own custom XMLAdapter
and for the simple String
it works fine but for List<String>
it adds <name>
which I do not want.
Following is my code for Employee.class
:
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement(name = "employee")
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee implements Serializable {
@XmlJavaTypeAdapter(CustomNameAdapter.class)
private Object name;
}
Following is my custom XMLAdapter CustomNameAdapter.class
:
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilderFactory;
import java.util.List;
public class CustomNameAdapter extends XmlAdapter<Object, Object> {
@Override
public Object unmarshal(Object v) {
return null;
}
//During the writing of XML handle either simple String or List<String> and write name field
@Override
public Object marshal(Object name) throws Exception {
System.out.println("Obtained Name Values : " + name);
final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
if (name instanceof String) {
final Element root = document.createElement("name");
root.setTextContent((String) name);
return root;
} else if (name instanceof List) {
final List<String> infoList = (List<String>) name;
final Element root = document.createElement("name");
for (final String item : infoList) {
final Element element = document.createElement("name");
element.setTextContent(item);
root.appendChild(element);
}
return root;
}
return null;
}
}
Following is my Main method MarshallerMain.class
:
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import java.util.ArrayList;
import java.util.List;
public class MarshallerMain {
public static void main(String[] args) throws JAXBException {
final Employee employee1 = new Employee("Name1");
final List<String> names = new ArrayList<String>();
names.add("one");
names.add("two");
names.add("three");
final Employee employee2 = new Employee(names);
final JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
final Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
System.out.println("Employee 1 Simple String : ");
jaxbMarshaller.marshal(employee1, System.out);
System.out.println("Employee 2 List of String : ");
jaxbMarshaller.marshal(employee2, System.out);
}
}
Following is my complete output that I get:
Employee 1 Simple String :
Obtained Name Values : Name1
<?xml version="1.0" encoding="UTF-8"?>
<employee>
<name>Name1</name>
</employee>
Employee 2 List of String :
Obtained Name Values : [one, two, three]
<?xml version="1.0" encoding="UTF-8"?>
<employee>
<name>
<name>one</name>
<name>two</name>
<name>three</name>
</name>
</employee>
But I want the output for List<String>
without additional wrapping with <name>
:
<employee>
<name>one</name>
<name>two</name>
<name>three</name>
</employee>
How to fix the issue during the XML marshalling to ensure I do not get additional wrapping for my <name>
?
Upvotes: 2
Views: 62
Reputation: 27958
Perhaps you could just do
@Data
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement(name = "employee")
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee implements Serializable {
private List<String> name;
public Employee(String name) {
this.name = name == null ? null : List.of(name);
}
}
Upvotes: 1