【问题标题】:Spring REST calls response type objects with tiny differencesSpring REST 调用响应类型对象,差异很小
【发布时间】:2019-07-31 10:04:41
【问题描述】:

我的服务需要返回两个相似的响应。第一个响应是days,它是一个名为availableDays 的字符串数组,另一个响应是times,它是一个名为availableTimes 的字符串数组。

我已经完成了第一个 (days),我的响应对象如下所示:

public class AvailableDaysTimesResponse {
  private String status;
  private String[] avaialbleDays;
  ...
}

问题是: 我是否需要创建一个不同的响应类并在其中有一个名为 availableTimesString[] 变量以返回 availableTimes 或者我可以以某种方式使用这个类来更改 中的数组变量的名称JSON 发回给调用者?

【问题讨论】:

    标签: java spring rest spring-mvc


    【解决方案1】:

    您可以使用 Jackson @JsonView 注释来使用相同的类。

    @JsonView 用于指示该字段将在哪个视图中 包括在序列化/反序列化时,非常有用 序列化时需要包含对象的不同字段 针对不同的用例。 Spring 支持 @JsonView 注解 对于 v≥4.1

    首先你必须创建一个类来声明你的视图。

    public class AvailableDaysTimesViews {
    
        public static class AvailableDaysResponse {
        }
    
        public static class AvailableTimesResponse {
        }
    }
    

    那么您必须将这些更改包含在AvailableDaysTimesResponse 类中

    public class AvailableDaysTimesResponse {
    
        @JsonView({
            AvailableDaysTimesViews.AvailableDaysResponse.class,
            AvailableDaysTimesViews.AvailableTimesResponse.class
        })
        private String status;
    
        @JsonView(AvailableDaysTimesViews.AvailableDaysResponse.class)
        private String[] avaialbleDays;
    
        public String getStatus() {
            return status;
        }
    
        public void setStatus(String status) {
            this.status = status;
        }
    
        @JsonProperty("availableTimes")
        @JsonView(AvailableDaysTimesViews.AvailableTimesResponse.class)
        public String[] getAvailableTimes() {
            return avaialbleDays;
        }
    
        public String[] getAvaialbleDays() {
            return avaialbleDays;
        }
    
        public void setAvaialbleDays(String[] avaialbleDays) {
            this.avaialbleDays = avaialbleDays;
        }   
    }
    

    如何在 Spring

    中使用您的 JSON 视图
    @JsonView(AvailableDaysTimesViews.AvailableDaysResponse.class)
    @RequestMapping("/days")
    public @ResponseBody
    AvailableDaysTimesResponse getDays() {
        AvailableDaysTimesResponse resp = new AvailableDaysTimesResponse();
        resp.setStatus("DONE");
        resp.setAvaialbleDays(new String[]{"MONDAY"});
        return resp;
    }
    
    @JsonView(AvailableDaysTimesViews.AvailableTimesResponse.class)
    @RequestMapping("/times")
    public @ResponseBody
    AvailableDaysTimesResponse getTimes() {
        AvailableDaysTimesResponse resp = new AvailableDaysTimesResponse();
        resp.setStatus("DONE");
        resp.setAvaialbleDays(new String[]{"ONCE", "TWICE"});
        return resp;
    }
    

    参考资料:

    Jackson @JsonView for serializing and deserializing object

    Jackson JSON Views with Spring

    【讨论】:

      【解决方案2】:

      不,您不需要创建单独的响应类。您可以在同一个类中添加另一个变量,Spring rest 根据从 api 接收到的值会自动将它们映射到响应类上,您所要做的就是根据您的使用获取各自的数组。您需要做的就是确保用于生成服务响应的类中的变量名称与将响应转换为的类中的变量名称相同。

      【讨论】:

        【解决方案3】:

        几个选项:

        选项 1

        继续使用您已经定义的单个字段。定义两个 get 方法并添加一个布尔标志来指示设置了哪个字段。根据此布尔标志从这些 get 方法中的每一个返回值:

        private static class Person {
            private String name;
            private boolean isKey1;
        
            public Person(String name, boolean isKey1) {
                this.name = name;
                this.isKey1 = isKey1;
            }
        
            public String getKey1() {
                return isKey1 ? name : null;
            }
        
            public String getKey2() {
                return isKey1 ? null : name;
            }
        }
        
        Person p1 = new Person("abc", true);
        Person p2 = new Person("xyz", false);
        

        此选项不是首选,因为您有多个字段可以有条件地控制。

        选项 2

        定义两个字段和两个 getter 方法。设置相应 API 中的值之一。

        private static class Person1{
            private String key1;
            private String key2;
        
            public Person1(String key1, String key2){
                this.key1 = key1;
                this.key2 = key2;
            }
        
            public String getKey1(){
                return this.key1;
            }
        
            public String getKey2(){
                return this.key2;
            }
        }
        
        Person1 p1 = new Person1("abc", null);
        Person1 p2 = new Person1(null, "xyz");
        

        选项 3

        定义两个不同的 DTO 类。简洁明了。

        注意事项:

        在选项 1 和选项 2 中,由于其中一个值为 null,请执行以下操作之一:

        在 application.properties 中添加以下内容:

        spring.jackson.default-property-inclusion=non_null
        

        在 DTO 类中添加如下注解:

        @JsonInclude(JsonInclude.Include.NON_NULL)
        

        【讨论】:

          【解决方案4】:

          如果您不想为所有不同的用例创建许多类,您始终可以使用简单的Map<String, Object> 作为返回值。这不是我通常会推荐的,但它是一种经常被忽视的快速方法(用于原型制作)。

          【讨论】:

            猜你喜欢
            • 2014-08-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-12-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多