0

我定义了以下 JsonViews:

public class EntityJsonView {
    public static class Detailed extends Abbreviated {
    }
    
    public static class AuditedDetailed extends Detailed {
    } 
    
    public static class Abbreviated {
        
    }
}

然后我有这些课程:

public Class Customer {

@JsonView(EntityJsonView.Abbreviated.class)
private Integer id;

@JsonView(EntityJsonView.Abbreviated.class)
private String name;

@JsonView(EntityJsonView.Detailed.class)
private String phone;

@JsonView(EntityJsonView.Detailed.class)
private List<Invoice> invoices;
}

public Class Invoice {

@JsonView(EntityJsonView.Abbreviated.class)
private Integer id;

@JsonView(EntityJsonView.Detailed.class)
private Customer customer;

@JsonView(EntityJsonView.Detailed.class)
private Employee salesman;

@JsonView(EntityJsonView.Abbreviated.class)
private Date invoiceDate;

@JsonView(EntityJsonView.Abbreviated.class)
private Double amount;
}

我这样返回我的客户列表:

@JsonView(EntityJsonView.Detailed.class)
    public ResponseEntity<List<Customer>> getCustomerList() {
        List<Customer> custs = customerService.getAll();
        return new ResponseEntity<List<Customer>>(custs , HttpStatus.OK);
}

虽然我希望使用详细视图对客户实例进行序列化,但我希望使用缩写视图对嵌套的发票实例进行序列化。同样,当我使用详细视图序列化发票列表时,我希望使用缩写视图序列化嵌套的客户实例。这不仅仅是递归问题,因为我还想删除许多其他属性。

我已经到处搜索了解决方案,但也许我没有使用正确的关键字。

我的前任使用@JsonIgnoreProperties 完成了这项工作,但事实证明这是一个维护问题。当一个新属性被添加到一个类中时,我必须寻找所有的忽略列表并决定是否需要忽略它。如果有相应的@JsonIncludeProperties 会更容易。

有没有人找到更好的方法来实现这一点?

4

1 回答 1

0

我想出了一种方法来做到这一点,它适用于我的环境。我发帖以防其他人有类似的问题。第一步是为每个顶级实体创建一个视图。在此示例中,它们将是 Foo、Bar 和 Snafu。这些都应该从缩写视图继承。

public class EntityViews {
  
 public static interface Abbr {}
    
 public static interface Foo extends Abbr {}
    
 public static interface Bar extends Abbr {}
    
 public static interface Snafu extends Abbr {}
    
 public static interface Detailed extends Foo, Bar, Snafu {}
}

我使用接口是因为它允许多重继承。所有主要的类视图最终都出现在详细视图中。现在上课:

@JsonView(EntityViews.Foo.class)
public class Foo {

@JsonView(EntityViews.Abbr.Class)
private Integer id;

@JsonView(EntityViews.Abbr.Class)
private String name;

private String description;

private Bar bar;

}

@JsonView(EntityViews.Bar.class)
public class Bar {

@JsonView(EntityViews.Abbr.Class)
private Integer id;

@JsonView(EntityViews.Abbr.Class)
private String name;

private List<Snafu> snafus;
}

@JsonView(EntityViews.Snafu.class)
public class Snafu {

@JsonView(EntityViews.Abbr.Class)
private Integer id;

@JsonView(EntityViews.Abbr.Class)
private String name;

@JsonView(EntityViews.Bar.class, EntityViews.Snafu.class)
@JsonIgnoreProperties("parent", "children")
private Snafu parent;

@JsonIgnoreProperties("parent", "children")
private List<Snafu> children;

}

现在,让我们做端点:

@RestController
@RequestMapping("/api/foos")
@CrossOrigin
public class FooController {

@JsonView(EntityViews.Foo.class)
@GetMapping("/")
    public ResponseEntity<List<Foo>> get() {
        List<Foo> list = service.getAll();
        return new ResponseEntity<List<Foo>>(list, HttpStatus.OK);
    }
}

@RestController
@RequestMapping("/api/bars")
@CrossOrigin
public class BarController {

@JsonView(EntityViews.Bar.class)
@GetMapping("/")
    public ResponseEntity<List<Foo>> get() {
        List<Bar> list = service.getAll();
        return new ResponseEntity<List<Bar>>(list, HttpStatus.OK);
    }
}

@RestController
@RequestMapping("/api/snafus")
@CrossOrigin
public class SnafuController {

@JsonView(EntityViews.Snafu.class)
@GetMapping("/")
    public ResponseEntity<List<Snafu>> get() {
        List<Snafu> list = service.getAll();
        return new ResponseEntity<List<Snafu>>(list, HttpStatus.OK);
    }
}

如我们所见,每个控制器都分配了与返回的实体相对应的视图。由于这些视图都继承自 Abbr,因此返回的所有其他实体都将应用 Abbr 视图。

请注意,在 Snafu 类中,父属性已分配给 Bar 和 Snafu 视图。因此,当您返回 Bar 端点时,您将获得该属性以及 Abbr 属性(我没有对此进行测试,所以 YMMV。如果它不像我认为的那样工作,将进行编辑)。

这个策略失败的一个地方是,如果你有与实体相同的类的属性。在这种情况下,您仍然必须使用 @JsonIgnoreProperties 来控制返回的内容,但这是一个很小的代价,因为不必在几乎每个实体属性上都有这些。

于 2021-09-16T14:03:13.953 回答