【问题标题】:Entity relationships in POSTed JSON with Spring Boot使用 Spring Boot 的 POSTed JSON 中的实体关系
【发布时间】:2017-02-08 01:37:26
【问题描述】:

Spring Boot(使用 Jackson)可以很好地处理 JSON 文档和 Java POJO 之间的对象映射。例如:

{ id: 5, name: "Christopher" }

可以接受:

@PostMapping("/students/{id}")
public Student Update(Long studentId, @RequestBody Student student) {

    studentRepository.save(student);

    return student;
}

并将正确映射到:

public class Student {
    private Long id;
    private String name;
    ...
}

但是 JSON 中的嵌套模型呢?

{ id: 5, name: "Christopher", grades: [ {id: 1, letter: 'A'} ] }

或者 JSON 中的可选模型?

{ id: 5, name: "Christopher" }
(Purposefully leaving out 'grades', though it could be accepted.)

或者表示在 JSON 中删除关联(例如使用 Rails 的 _destroy 标志)?

{ id: 5, name: "Christopher", grades: [ {id: 1, letter: 'A', _destroy: true} ] }

或者通过省略 ID 创建关联?

{ id: 5, name: "Christopher", grades: [ {letter: 'A-'} ] }

Spring Boot 是否支持这些想法?

【问题讨论】:

  • 如果你的意思是“可选模型”,那么想想 Optional 什么的;你不应该在 Pojos 中使用 Optionals。
  • 不一定是可选模型,只是可选模型是否应该在 JSON 中。如果“学生”有一个“成绩”列表,但我只想更新学生的姓名,我不想每次都发布他们的“成绩”数组。
  • 我使用数据传输对象 (DTO) 来解决您描述的问题。您也可以在不想序列化的字段上添加@JsonIgnore 注解。

标签: java json spring jackson


【解决方案1】:

但是 JSON 中的嵌套模型呢?

嵌套模型按照您的预期进行映射,假设您有以下模型:

public class Product {
    private String name;
    private List<Price> prices;
}


public class ProductPrice {
     Long idPrice;
     Integer amountInCents;
}

Jackson 将从这个 Schema 创建以下 JSON:

{
    "name":"Samsung Galaxy S7",
    "prices":[
         {
              "idPrice":0,
              "amountInCents": 100
         }
    ]
}

或者 JSON 中的可选模型?

您可以使用@JsonIgnore 注释字段。例如,如果您使用 @JsonIgnore 注释价格,则不会从 jackson 序列化任何价格。

或表示在 JSON 中删除关联(例如使用 Rails 的 _destroy 标志)?

我会创建一个额外的映射来删除关联。这还有另一个优点,API 是自我解释的。

 @DeleteMapping("/students/{id}/grade/{idGrade}")
 public Student Update(Long studentId, @PathVariable Long idGrade) {

     studentService.deleteGrade(studentId,idGrade);

     return student;
}

或者通过省略 ID 创建关联?

我还要在这里创建一个额外的映射:

@PostMapping("/students/{id}/grade")
public Student Update(Long studentId, @PathVariable String grade) {

     studentService.addGrade(studentId,grade);

     return student;
}

注意:我不直接使用存储库,我创建了一个服务层并且每个存储库都具有包保护访问权限。在服务层中,您可以创建 addGrade、deleteGrad、addStudent、deleteStudent 等方法

【讨论】:

  • 谢谢,这是一个非常完整的答案。但是,如果我只想在碰巧包含数据的情况下序列化嵌套模型怎么办? @JsonIgnore 就好像该关联根本不存在一样。但我可能想同时创建一个带有嵌套对象的对象,或者我可能希望将其排除在外。是否支持这种行为?
  • 我从未尝试过,但看看 Jackson JSON Views。我认为这应该符合您的目标。这是一篇不错的博文:baeldung.com/jackson-json-view-annotation
猜你喜欢
  • 2021-06-05
  • 2014-08-10
  • 2022-12-11
  • 2018-07-04
  • 2017-10-01
  • 2020-04-03
  • 2019-10-01
  • 2017-07-12
  • 2021-08-18
相关资源
最近更新 更多