对于Jersey / JAXB,是否可以使用相同的POJO作为“父”和“子”,但在用作“孩子”时删除某些属性?

时间:2012-06-15 23:46:49

标签: java json jaxb jersey jax-rs

我有两个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对象吗?

2 个答案:

答案 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实体,版本控制等方面更为复杂。