Reputation: 490
I'm trying to map a json pojo to an xml pojo using ModelMapper...
In the code, below, I was expecting to see the content of "jsonSource" (source) POJO transferred to xmlDest POJO (target)
...however, the code fails - as no data in ("jsonSource") was reflected in the target ("xml"). i.e., as the difference in the ".size()" method value indicates.
SOURCE (json)
jsonSource.getEmployees().size() == 2
TARGET (xml)
xml.getEmployees().size() == 0 <<< should also be 2
code snippet...
@Test
public void givenJsonSource_whenMapToXmlDest_thenFieldsMapCorrectly() throws Exception {
Employees jsonSource = new Employees();
List<Employee> employees = new ArrayList<>();
Employee employee1 = new Employee();
employee1.setName("thename");
employee1.setGender("M");
employee1.setAge(30);
employees.add(employee1);
Employee employee2 = new Employee();
employee2.setName("thename2");
employee2.setGender("M2");
employee2.setAge(32);
employees.add(employee2);
jsonSource.setEmployees(employees);
aaa.bbb.ccc.jar.generated.Employees xml = mapper.map(jsonSource, aaa.bbb.ccc.jar.generated.Employees.class);
System.out.println("jsonSource.getEmployees().size()=>" + jsonSource.getEmployees().size()); // <<< 2
System.out.println("xmlDest.getEmployee().size()=>" + xml.getEmployees().size()); // <<< 0
// verify fields
assertEquals(xml.getEmployees().get(0).getName(), jsonSource.getEmployees().get(0).getName());
}
...although jsonSource.getEmployees().size is 2, the xmlDest.getEmployee.size() is 0
Here is the Employee json pojo class (referenced above)...
package aaa.bbb.ccc.jar;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Employee {
@JsonProperty("name")
String name;
@JsonProperty("gender")
String gender;
@JsonProperty("age")
Integer age;
public Employee() {
}
public Employee(String name, String gender, Integer age) {
this.name = name;
this.gender = gender;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Employee{" + "name=" + name + ", gender=" + gender + ", age=" + age + '}';
}
}
Here is the Employees json POJO class...
package aaa.bbb.ccc.jar;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
@JsonRootName(value = "Employees")
public class Employees {
@JsonProperty(value = "Employees")
protected List<Employee> employees;
public Employees() {
}
public List<Employee> getEmployees() {
if (employees == null) {
employees = new ArrayList<>();
}
return this.employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
@Override
public String toString() {
return "Employees{" + "employees=" + employees + '}';
}
}
Here is the generated xml POJO (aaa.bbb.ccc.jar.generated.Employee)
//
// This file was generated by the Eclipse Implementation of JAXB, v3.0.0
// See https://eclipse-ee4j.github.io/jaxb-ri
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2024.04.12 at 08:27:40 AM EDT
//
package aaa.bbb.ccc.jar.generated;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlType;
/**
* <p>Java class for Employee complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="Employee">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <all>
* <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="Gender" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="Age" type="{http://www.w3.org/2001/XMLSchema}int" minOccurs="0"/>
* </all>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Employee", propOrder = {
})
public class Employee {
@XmlElement(name = "Name")
protected String name;
@XmlElement(name = "Gender")
protected String gender;
@XmlElement(name = "Age")
protected Integer age;
/**
* Gets the value of the name property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setName(String value) {
this.name = value;
}
/**
* Gets the value of the gender property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getGender() {
return gender;
}
/**
* Sets the value of the gender property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setGender(String value) {
this.gender = value;
}
/**
* Gets the value of the age property.
*
* @return
* possible object is
* {@link Integer }
*
*/
public Integer getAge() {
return age;
}
/**
* Sets the value of the age property.
*
* @param value
* allowed object is
* {@link Integer }
*
*/
public void setAge(Integer value) {
this.age = value;
}
}
Here is the generated xml pojo (i.e., aaa.bbb.ccc.jar.generated.Employees)
//
// This file was generated by the Eclipse Implementation of JAXB, v3.0.0
// See https://eclipse-ee4j.github.io/jaxb-ri
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2024.04.12 at 08:27:40 AM EDT
//
package aaa.bbb.ccc.jar.generated;
import java.util.ArrayList;
import java.util.List;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="Employees" type="{http://www.aaa.bbb.ccc/jar/mmdemo}Employee" maxOccurs="unbounded" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"employees"
})
@XmlRootElement(name = "Employees")
public class Employees {
@XmlElement(name = "Employees")
protected List<Employee> employees;
/**
* Gets the value of the employees property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the Jakarta XML Binding object.
* This is why there is not a <CODE>set</CODE> method for the employees property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getEmployees().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Employee }
*
*
*/
public List<Employee> getEmployees() {
if (employees == null) {
employees = new ArrayList<Employee>();
}
return this.employees;
}
}
this is the xsd used to generate the XML classes
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
targetNamespace="http://www.aaa.bbb.ccc/jar/mmdemo"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:es="http://www.aaa.bbb.ccc/jar/mmdemo"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="Employee">
<xs:all>
<xs:element name="Name" type="xs:string" minOccurs="0" />
<xs:element name="Gender" type="xs:string" minOccurs="0" />
<xs:element name="Age" type="xs:int" minOccurs="0" />
</xs:all>
</xs:complexType>
<xs:element name="Employees">
<xs:complexType>
<xs:sequence>
<xs:element name="Employees" type="es:Employee" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
appreciate any help/hints at understanding what might be missing that would make the above work
Upvotes: 0
Views: 46
Reputation: 490
looks like "a" solution is to individually map elements of Employees in a for-loop...
for (Employee sourceEmployee : sourceEmployees) {
aaa.bbb.ccc.jar.generated.Employee destEmployee = mapper.map(sourceEmployee, aaa.bbb.ccc.jar.generated.Employee.class);
xml.getEmployees().add(destEmployee);
}
almost certainly it's not necessarily the only solution -but, it works now....
@Test
public void givenJsonSource_whenMapToXmlDest_thenFieldsMapCorrectly() throws Exception {
Employees jsonSource = new Employees();
List<Employee> employees = new ArrayList<>();
Employee employee1 = new Employee();
employee1.setName("thename");
employee1.setGender("M");
employee1.setAge(30);
employees.add(employee1);
Employee employee2 = new Employee();
employee2.setName("thename2");
employee2.setGender("M2");
employee2.setAge(32);
employees.add(employee2);
jsonSource.setEmployees(employees);
aaa.bbb.ccc.jar.generated.Employees xml = new aaa.bbb.ccc.jar.generated.Employees();
List<Employee> sourceEmployees = jsonSource.getEmployees();
for (Employee sourceEmployee : sourceEmployees) {
aaa.bbb.ccc.jar.generated.Employee destEmployee = mapper.map(sourceEmployee, aaa.bbb.ccc.jar.generated.Employee.class);
xml.getEmployees().add(destEmployee);
}
System.out.println("jsonSource.getEmployees().size()=>" + jsonSource.getEmployees().size());
System.out.println("xmlDest.getEmployee().size()=>" + xml.getEmployees().size());
// verify fields
assertEquals(xml.getEmployees().get(0).getName(), jsonSource.getEmployees().get(0).getName());
}
Upvotes: 0