3

我有两个 Java 对象,Company 和 Employee。它们都使用 Jersey/JAXB 注释进行注释,因此我可以调用 RESTful 服务来 HTTP GET 它们。从本质上讲,Company 是 Employee 的“父”对象,如果为 Company 执行 GET,我想做的只是在 JSON 响应中为员工的子列表提供属性的子集。但是,在为 Employee 本身执行 GET 时,我仍然想返回 Employee 的所有属性。

我一直在努力解决这个问题,但我不太确定该怎么做。它看起来很基本,但我无法在网上找到任何示例(也许我在谷歌搜索错误的东西)。

公司.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...
}

雇员.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 对象下的员工列表仅返回几个指定的 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 对象?

4

2 回答 2

4

您可以使用 anXmlAdapter来解决此用例:

员工适配器

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 表示的位置添加注释。这意味着您可以删除模型中的一些注释:

于 2012-06-16T10:12:36.853 回答
1

我已经用接口做到了这一点。创建一个 IEmployee 和 IEmployeeLight 接口。

IEmployeeLight 具有基础知识,IEmployee 对其进行了扩展并添加了完整的数据。您可以使集合返回 IEmployeeLight 类型。适当地注释两个接口。您可能需要在服务定义上使用 XmlSeeAlso,因为 JAXB 不能绑定到接口,除非它有实现提示。

抱歉,如果这还不够详细,这是一个复杂的话题,没有白板很难做到公正。

请注意,我并不是说这个解决方案是最佳的,只是对我们有用。

我们的用例在 DTO、JPA 实体、版本控制等方面更加复杂。

于 2012-06-15T23:52:57.513 回答