【问题标题】:Spring, JSON serializer, serialize a field only in some casesSpring,JSON 序列化器,仅在某些情况下序列化一个字段
【发布时间】:2020-01-26 20:14:49
【问题描述】:

我有一个班级订单:

@Data
@Entity
public class Order {

  private List<Project> projects;

  // more fields
}

我的控制器中有两个 API 方法:

  @GetMapping
  public ResponseEntity<List<Order>> getOrders() {
    return ResponseEntity.ok(orderService.getOrders());
  }

  @GetMapping("/{id}")
  public ResponseEntity<Order> getOrder(@PathVariable long id) {
    return ResponseEntity.ok(orderService.getOrder(id));
  }

所以在这种情况下,projects 总是通过 JSON 发送,如果它存在,它只是被序列化,如果它不存在,它被懒惰地获取然后序列化。我可以通过用@JsonIgnore 注释字段来避免它被序列化。但问题是我有时想发送它,有时我不发送。例如在getOrders() 我不希望projects 被序列化。在getOrder(...) 中,我希望projects 被序列化。有没有办法在运行时在自定义代码中或通过注释告诉我想在一种特定情况下而不是在另一种情况下发送它?我唯一想到的是 - 在序列化之前不久 - 我可以用 null 初始化 projects 并用 @JsonInclude(JsonInclude.Include.NON_NULL) 注释实体。这样它就不会被发送,如果我想发送它,我可以避免用 null 初始化它。但显然我不想迭代 O(n) 中的每个 Order 只是为了将其 projects 初始化为 null。

【问题讨论】:

  • 您可以使用Jackson JSON view 来指示何时反序列化该属性
  • 我认为 Jackson 的 JsonDeserializer&lt;T&gt; 专门用于此类目的。你试过吗?您可以查看this StackOverflow question
  • 创建一个视图模型对象并解析到它

标签: java json spring


【解决方案1】:

使用“JSON 视图”很容易实现。

首先,定义一些类来表示每个视图(例如内部/外部):

public class OrderViews {
    public static class OnlySomeFields {}
    public static class AllFields extends OnlySomeFields {}
}

接下来,在您的班级上,为每个字段分配一个视图:

public class Order {

    @JsonView(OrderViews.OnlySomeFields.class)
    private String foo;

    @JsonView(OrderViews.AllFields.class)
    private String bar;

    // getters/setters/etc
}

然后,在您的控制器中,您可以为每种方法指定要使用的视图:

@RestController
public class MyController {

    @JsonView(OrderViews.AllFields.class)
    @GetMapping("/with-all-fields")
    public Order getOrderAllFields() {
        return orderService.getOrder();
    }

    @JsonView(OrderViews.OnlySomeFields.class)
    @GetMapping("/with-some-fields")
    public Order getOrderAllFields() {
        return orderService.getOrder();
    }

}

使用此设置,导航到 /with-all-fields 会返回一个包含 foobar 的 JSON,而导航到 /with-some-fields 会返回一个仅包含 foo 的 JSON。

您可以使用此技术选择性地序列化特定字段,并且应该能够将其应用于您的用例。

【讨论】:

  • 假设foo 有一个孩子moo。是否可以指定两个order 视图,一个具有foo 作为子级,foo 具有moo 作为一个子级。另一个有foo 作为孩子但foo 没有moo 作为孩子吗?所以我想用相同的孩子定义两个order 视图,但孩子的孩子不同。
  • 好的,我刚刚想通了。我也可以使用订单视图中的视图类来注释子字段的子字段。
  • 是的,您将使用相同的技术,但在您的 Project 类上。它是 Jackson 的特性,而不是 Spring 特性本身,并且使用 Jackson 的标准序列化接口递归地工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-24
  • 1970-01-01
  • 2019-05-03
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多