For Jersey/JAXB, is it possible to use the same POJO as both 'parent' and 'child' but remove certain attributes when being used as a 'child'?
java, jax-rs, jaxb, jersey, json
Solution
You could use an `XmlAdapter` to solve this use case:
EmployeeAdapter
The `XmlAdapter` will convert the fully populated `Employee` to another instance with only the fields you want marshalled to XML populated. Since this is a copy it does not affect the original object model.
package forum11059499;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class EmployeeAdapter extends XmlAdapter<Employee, Employee>{
@Override
public Employee marshal(Employee employee) throws Exception {
Employee partialEmployee = new Employee();
partialEmployee.setEmployeeId(employee.getEmployeeId());
partialEmployee.setEmployeeName(employee.getEmployeeName());
return partialEmployee;
}
@Override
public Employee unmarshal(Employee employee) throws Exception {
return employee;
}
}
Company
The `@XmlJavaTypeAdapter` annotation is used to specify the `XmlAdapter` on the desired property.
package forum11059499;
import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
public class Company {
private String companyName;
private String companyType;
private List<Employee> employees = new ArrayList<Employee>();
// getters and setters with @XmlElement on each attribute
// ...etc...
@XmlElement
@XmlJavaTypeAdapter(EmployeeAdapter.class)
public List<Employee> getEmployees() {
return employees;
}
// ...etc...
}
For More Information
- http://blog.bdoughan.com/search/label/XmlAdapter
- http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html
I noticed that you had the following comment in your code:
// getters and setters with @XmlElement on each attribute
Because JAXB (JSR-222) implementations are configuration by exception, you only need to add annotations where you want the XML representation from the default. This means you may be able to remove some of the annotations you have in your model:
- http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics
Problem
I have two Java objects, Company and Employee. They are both annotated with Jersey/JAXB annotations so that I can call RESTful services to HTTP GET them. Essentially, Company is the "parent" object to Employee, and what I want to do is provide only a subset of the attributes for the child list of Employees in the JSON response if doing a GET for the Company. But, I still want to return all the attributes for the Employee when doing a GET for the Employee itself. I've been trying to get my head around this, but I'm not quite sure how to do it. It seems pretty basic, but I haven't been able to find any examples online (maybe I'm google searching the wrong things). Company.java ``` @XmlRootElement public class Company { private String companyName; private String companyType; private List<Employee> employees = new ArrayList<Employee>(); // getters and setters with @XmlElement on each attribute //...etc... @XmlElement public List<Employee> getEmployees() { return employees; } //...etc... } ``` Employee.java ``` @XmlRootElement public class Employee{ private String employeeId; private String employeeName; private String employeeType; // getters and setters with @XmlElement on each attribute //...etc... @XmlElement public String getEmployeeId() { return employeeId; } //...etc... } ``` Now, I have a RESTful service to do an HTTP GET on the Company object and the Employee object: ``` public class infoService{ @GET @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response getCompany(String Id) { //.... } @GET @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response getEmployee(String Id) { //.... } } ``` For getting the Employee object, all the attributes are returned, as expected. So it looks something like this: ``` { "employeeId": "1A2-B35", "employeeName": "John Doe", "employeeType": "Engineer" } ``` When doing a GET for the Company object, I want the list of Employees under the Company object to return only a couple specified attributes for the Employee (i.e. employee name and employee id only). Therefore, my desired JSON response would look something like this: ``` { "companyName": "Acme", "companyType": "Services", "employees": [ { "employeeId": "123_ABC", "employeeName": "John Doe" }, { "employeeId": "456_XYZ", "employeeName": "Jane Doe" } ] } ``` However, of course, it returns all the Employee attributes in the employees list, like this: ``` { "companyName": "Acme", "companyType": "Services", "employees": [ { "employeeId": "123_ABC", "employeeName": "John Doe", "employeeType": "Engineer" }, { "employeeId": "456_XYZ", "employeeName": "Jane Doe", "employeeType": "Executive" } ] } ``` Is this possible to do this solely with the annotations? Or is there some other way of doing this short of creating my own JSON object?