我有两个Java对象,Company和Employee。它们都使用Jersey / JAXB注释进行注释,以便我可以将RESTful服务调用到HTTP GET它们。从本质上讲,Company是Employee的“父”对象,我想要做的是,如果为公司进行GET,则只为JSON响应中的Employees子列表提供一部分属性。但是,我仍然希望在为Employee本身进行GET时返回Employee的所有属性。
我一直试图解决这个问题,但我不太清楚如何做到这一点。这似乎很基本,但我无法在网上找到任何例子(也许我在谷歌搜索错误的东西)。
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...
}
现在,我有一个RESTful服务来对Company对象和Employee对象执行HTTP GET:
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) {
//....
}
}
要获取Employee对象,将按预期返回所有属性。所以它看起来像这样:
{
"employeeId": "1A2-B35",
"employeeName": "John Doe",
"employeeType": "Engineer"
}
在为Company对象执行GET时,我希望Company对象下的Employees列表只返回Employee的几个指定属性(即仅员工姓名和员工ID)。因此,我想要的JSON响应看起来像这样:
{
"companyName": "Acme",
"companyType": "Services",
"employees": [
{
"employeeId": "123_ABC",
"employeeName": "John Doe"
},
{
"employeeId": "456_XYZ",
"employeeName": "Jane Doe"
}
]
}
但是,当然,它会返回员工列表中的所有Employee属性,如下所示:
{
"companyName": "Acme",
"companyType": "Services",
"employees": [
{
"employeeId": "123_ABC",
"employeeName": "John Doe",
"employeeType": "Engineer"
},
{
"employeeId": "456_XYZ",
"employeeName": "Jane Doe",
"employeeType": "Executive"
}
]
}
这可以仅通过注释来实现吗?或者还有其他方法可以创建我自己的JSON对象吗?
答案 0 :(得分:4)
您可以使用XmlAdapter
来解决此用例:
<强> EmployeeAdapter 强>
XmlAdapter
会将完全填充的Employee
转换为另一个实例,只填充要编组为XML的字段。由于这是一个副本,因此不会影响原始对象模型。
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;
}
}
<强>公司强>
@XmlJavaTypeAdapter
注释用于指定所需属性的XmlAdapter
。
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...
}
了解更多信息
我注意到您的代码中有以下注释:
//每个属性都带有@XmlElement的getter和setter
因为JAXB(JSR-222)实现是异常配置,所以您只需要在默认情况下添加XML表示的注释。这意味着您可以删除模型中的一些注释:
答案 1 :(得分:1)
我用接口完成了这个。创建一个IEmployee和IEmployeeLight接口。
IEmployeeLight具有基础,IEmployee扩展它并添加完整的脂肪数据。您可以使集合返回一种IEmployeeLight。适当地注释两个接口。您可能需要在服务定义上使用XmlSeeAlso,因为JAXB无法绑定到接口,除非它有实现提示。
对不起,如果这还不够详细,这是一个复杂的话题,如果没有白板,很难做到这一点。
请注意,我并不是说这个解决方案是最优的,只是对我们有用的。
我们的用例在DTO,JPA实体,版本控制等方面更为复杂。