如何设计REST服务以响应不同级别的信息?

时间:2018-02-15 09:42:15

标签: spring rest api-design

我希望有一个服务可以响应不同级别的信息:

等级1:

{
    "field_1": "value_1",
    "field_2": "value_2"
}

等级2:

{
    "field_1": "value_1",
    "field_2": "value_2",
    "field_3": "value_3"
}

等级3:

{
    "field_1": "value_1",
    "field_2": "value_2",
    "field_3": "value_3",
    "field_4": "value_4"
}

我的第一种方法是在请求中使用一个参数,如下所示:

@RestController
public <ResponseObject> getInfo(..., @RequestParam levelInfo) {
    service.getInfo(..., levelInfo);
}

@Service
public <ResponseObject> getInfo(..., levelInfo) {
    if (levelInfo == 1)
        return setupResponseLevel1();
    if (levelInfo == 2)
        return setupResponseLevel1();
    if (levelInfo == 3)
        return setupResponseLevel1();
}
private <ResponseObject> setupResponseLevel1() {
    responseObject.setField_1(repository.getField1());
    responseObject.setField_2(repository.getField2());
    return responseObject;
}
private <ResponseObject> setupResponseLevel2() {
    responseObject = this.setupResponseLevel1();
    responseObject.setField_3(repository.getField3());
    return responseObject;
}
private <ResponseObject> setupResponseLevel3() {
    responseObject = this.setupResponseLevel2();
    responseObject.setField_4(repository.getField4());
    return responseObject;
}

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class ResponseObject {
    private String field_1;
    private String field_2;
    private String field_3;
    private String field_4;

    // Getters & setters...
}

我的API非常庞大,我需要找到一种可以在许多服务中重用的模式。

你知道更清洁的方法吗?

编辑:对不起,我没有用正确的精确度解释。

我喜欢这些答案的想法,但我已经为@Service添加了更多代码,以便您了解问题不仅仅是响应的呈现(JSON),而且还节省了获取成本信息(查询BBDD)。

2 个答案:

答案 0 :(得分:0)

您可以使用@JsonView注释。一个简单的例子看起来像这样

public class Views {
    public static class LevelOne {
    }

    public static class LevelTwo extends LevelOne {
    }
}


public class ResponseObject {

    @JsonView(Views.LevelOne.class)
    private String field_1;

    @JsonView(Views.LevelOne.class)
    private String field_2;

    @JsonView(Views.LevelTwo.class)
    private String field_3;

}

和序列化的方法

public String toJson(Class<?> view) {
    ObjectMapper objectMapper = new ObjectMapper();
    return objectMapper.writerWithView(view).writeValueAsString(this);
}

如果使用toJson作为参数调用Views.LevelOne.class方法,则只会将field_1和field_2序列化。如果使用Views.LevelTwo.class调用它,则会序列化所有三个字段。

您可以根据建议选择参数使用哪个视图。

答案 1 :(得分:0)

如下所示的URL方案:

https://your.api/info/2

然后

@RequestMapping("/info/{levelInfo}")
public <ResponseObject> getInfo(..., @PathVariable String levelInfo) {

其中2是等级。由于级别是您的域的一部分,即它与您的客户有关,您可以在数据库中捕获每个字段的级别列1,2,3,4等,然后使用存储库:

repository.findByLevelLessThanEqual(levelInfo)

可以返回包含所有必填字段的信息包。因此,如果您要求级别1,则只能获得1级字段。如果你要求4级,你可以获得所有领域,包括4级

Spring JPA LessThanEqual documentation