Dans l'écosystème Java, la manipulation de données XML et le mappage d'objets sont des opérations courantes. Cette section technique détaille l'utilisation de trois bibliothèques essentielles : dom4j pour l'analyse XML, XStream pour la sérialisation, et Orika pour le transfert de propriétés entre objets.
dom4j
dom4j est une bibliothèque qui utilise le modèle DOM pour analsyer et naviguer dans les documents XML de manière felxible.
<!-- Dépendance Maven -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.4</version>
</dependency>
<!-- Fichier catalog.xml utilisé pour la démonstration -->
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<product type="electronics">
<name>Smartphone</name>
<brand>TechCorp</brand>
<price>699.99</price>
</product>
<product type="accessories">
<name>Wireless Charger</name>
<brand>PowerUp</brand>
<price>25.50</price>
</product>
</catalog>
@Test
public void parseCatalogXml() throws Exception {
File xmlFile = new File("catalog.xml");
SAXReader saxReader = new SAXReader();
Document xmlDoc = saxReader.read(xmlFile);
Element root = xmlDoc.getRootElement();
System.out.println("Noeud racine : " + root.getName());
for (Element product : root.elements("product")) {
System.out.println("Produit : " + product.elementText("name"));
}
}
XStream
XStream permet de conevrtir des JavaBeans en XML ou en JSON, et inversement, en s'appuyant sur la réflexion. Il offre une grande flexibilité pour la sérialisation.
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.20</version>
</dependency>
<!-- Nécessaire pour la conversion JSON avec le driver Jettison -->
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.5.4</version>
</dependency>
Modèles de données pour les conversions :
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private String fullName;
private int employeeId;
private String department;
private double salary;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Staff {
private String fullName;
private int employeeId;
private String department;
}
Conversion entre XML et JavaBean :
@Test
public void convertToAndFromXml() throws Exception {
XStream xstream = new XStream(new StaxDriver());
// Configuration de sécurité pour autoriser la sérialisation
xstream.addPermission(AnyTypePermission.ANY);
xstream.alias("staffMember", Employee.class);
xstream.aliasField("identifier", Employee.class, "employeeId");
Employee emp = new Employee("Alice Smith", 1001, "IT", 75000.0);
String xmlOutput = xstream.toXML(emp);
System.out.println(xmlOutput);
Employee parsedEmp = (Employee) xstream.fromXML(xmlOutput);
System.out.println(parsedEmp);
}
Conversion entre JSON et JavaBean avec différents drivers :
@Test
public void handleJsonSerialization() {
// Driver hiérarchique sans noeud racine
XStream jsonMapper = new XStream(new JsonHierarchicalStreamDriver() {
@Override
public HierarchicalStreamWriter createWriter(Writer out) {
return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE);
}
});
jsonMapper.addPermission(AnyTypePermission.ANY);
Employee emp = new Employee("Bob Johnson", 1002, "HR", 65000.0);
System.out.println(jsonMapper.toXML(emp));
// Driver Jettison pour la lecture et l'écriture
XStream jettisonMapper = new XStream(new JettisonMappedXmlDriver());
jettisonMapper.addPermission(AnyTypePermission.ANY);
jettisonMapper.setMode(XStream.NO_REFERENCES);
String jsonStr = jettisonMapper.toXML(emp);
System.out.println(jsonStr);
}
Orika Core
Orika est une bibliothèque de mappage d'objets qui génère du bytecode pour copier les propriétés, offrant des performances supérieures aux approches basées sur la réflexion comme BeanUtils.
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.5.4</version>
</dependency>
@Test
public void mapEmployeeToStaff() {
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Employee.class, Staff.class)
.field("fullName", "fullName")
.byDefault()
.register();
MapperFacade mapper = mapperFactory.getMapperFacade();
Employee source = new Employee("Charlie Brown", 1003, "Finance", 80000.0);
Staff destination = mapper.map(source, Staff.class);
System.out.println(destination);
}