【问题标题】:Spring HATEOAS/Jackson with resources and resource assembler带有资源和资源组装器的 Spring HATEOAS/Jackson
【发布时间】:2016-11-05 14:19:01
【问题描述】:

由于我的两个 JPA 实体(任务和作业)的双向关系中存在嵌套循环,我收到了 Jackson 错误。我开始研究并部分设法使用@JsonManagedReference 和@JsonBackReference 注释来解决这个问题,但是这种方法仅在我在我的实体中使用注释时才有效,这以跳过我的 JobResource/JobResourceAssembler 和 TaskResource/TaskResourceAssembler 的 JSON 序列化结束,得到HATEOASless 和 HALless json 响应。

有没有办法让我的资源管理这个序列化/反序列化?

一些代码(这样我得到了一个 json 响应,但是交换了 HATEOASless 和 HALless):

@Entity
public class Task {

@Id
@GeneratedValue
private Long id;

@OneToMany(mappedBy="task")
@JsonManagedReference
private List<Job> job = new ArrayList<Job>();

//constructors, getter, setter...

@Entity
public class Job {

@Id
@GeneratedValue
private Long id;

@ManyToOne
@JsonBackReference
@JoinColumn(name = "task_id", updatable = true, insertable = true, nullable = true)
private Task task;

//constructor, setter, getter.

HATEOASless 响应(工作应该有链接)

{
"_embedded": {
"tasks": [
  {
    "name": "Task",
    "description": "Task Description",
    "createdAt": 1467583658749,
    "updatedAt": null,
    "deletedAt": null,
    "isActive": true,
    "estimatedStartDate": null,
    "startDate": null,
    "estimatedDateEnd": null,
    "dateEnd": null,
    "ids": 1,
    "risk": null,
    "job": [
      {
        "id": 2,
        "name": "Job",
        "description": "Job Description",
        "createdAt": 1467583673859,
        "updatedAt": null,
        "deletedAt": null,
        "isActive": true
      },
      {
        "id": 3,
        "name": "Job2",
        "description": "Job Description",
        "createdAt": 1467583676138,
        "updatedAt": null,
        "deletedAt": null,
        "isActive": true
      },
      {
        "id": 4,
        "name": "Job3",
        "description": "Job Description",
        "createdAt": 1467583679339,
        "updatedAt": null,
        "deletedAt": null,
        "isActive": true
      }
    ],
    "_links": {
      "self": {
        "href": "http://127.0.0.3:7890/api/v1/tasks/1"
      },
      "task": {
        "href": "http://127.0.0.3:7890/api/v1/tasks/1"
      }
    }
  }
]

【问题讨论】:

    标签: java json spring jackson spring-hateoas


    【解决方案1】:

    我和我的同事解决了这个问题。首先:问题是杰克逊直接序列化我们的相关实体,忽略了spring HATEOAS的资源。这是因为我们的资源是由对象列表提供的,没有资源列表,所以我们改变了:

    @Relation(collectionRelation = "tasks")
    public class TaskResource extends ResourceSupport {
    
        private List<JobResource> job = new ArrayList<JobResource>();
    

    现在,由于我的资源列表由资源而不是常规实体提供,我们提供了一项服务,可以用常规作业填充 List 作业。由于实体有自己的资源,基本上是一样的,这个过程发展得相当快:

    public List<JobResource> findJobsFromTask(Long id) {
    
        Task task = taskRepository.findOne(id);
        List<Job> jobs = task.getJob(); 
        List<JobResource> jobResourceList = new ArrayList<JobResource>();
    
        for (Job job : jobs) {
            jobResourceList.add(new JobResourceAssembler().toResource(job));
        }
        return jobResourceList;
    }
    

    有了这个,我们只需要修复汇编器,让它添加新的 JobResource:

    @Override
    public TaskResource toResource(Task task) {
        taskResource.setJob(taskService.findJobsFromTask(task.getId()));
    }
    

    这就是我们的解决方案。如果有更好的,请发表评论或其他答案进行讨论。

    编辑:当嵌套资源超过 3 个时,可能需要手动将所有内容添加到资源中。假设我们有 3 个资源:项目 -> 任务 -> 工作。如果我们采用前面的方法,那么它将以嵌套的 null 错误结束。服务:

    @Override
    public List<TaskResource> findTaskFromProject(Long id) {
    
        Project project = projectRepository.findOne(id);
        List<Task> tasks = project.getTask();
        List<TaskResource> taskResourceList = new ArrayList<TaskResource>();
    
        for (Task task : tasks) {
            TaskResource taskResource = new TaskResource();
            taskResource.setName(task.getName());
            taskResource.setDescription(task.getDescription());
            taskResource.setCreatedAt(task.getCreatedAt());
            taskResource.setUpdatedAt(task.getUpdatedAt());
            taskResource.setDeletedAt(task.getDeletedAt());
            taskResource.setIsActive(task.getIsActive());
            taskResource.setRisk(task.getRisk());
            //taskResource.setDocumentState(task.getDocumentState());
            taskResource.setEstimatedStartDate(task.getEstimatedStartDate());
            taskResource.setStartDate(task.getStartDate());
            taskResource.setEstimatedDateEnd(task.getEstimatedDateEnd());
            taskResource.setDateEnd(task.getDateEnd());
            taskResource.setIds(task.getId());
            taskResource.setJob(taskService.findJobsFromTask(task.getId()));
            taskResource.add(linkTo(TaskController.class).slash("").slash(task.getId()).withSelfRel());
            taskResource.add(linkTo(TaskController.class).slash("").slash(task.getId()).withRel("task"));
    
            taskResourceList.add(taskResource);
        }
    
        return taskResourceList;
    }
    

    这样,我们得到了一个项目 -> 任务 -> 作业 JSON 响应 full hatoas /hal。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-17
      • 2014-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-03
      相关资源
      最近更新 更多