修改REST API响应以仅包括查询参数中请求的字段

我想发送仅包含GET api请求字段的响应。减少响应的总大小。

例如, 默认行为,何时请求特定字段

GET /v1/users/

{
   "data" : 
     [
        {
            "name" : "User1","phone" : "800-999-9999","city" : "XYZ1","country" : "PQR1"
        },{
            "name" : "User2","city" : "XYZ2","country" : "PQR2"
         }
     ]
}

用例,所需字段作为查询参数传递

GET /v1/users/?fields=name,city

{
   "data" : 
     [
        {
            "name" : "User1","city" : "XYZ1"
        },"city" : "XYZ2"
         }
     ]
}

跨“ https://github.com/monitorjbl/json-view”。但是被团队击落了。

如何使用Spring Boot实施此功能?使用Java微服务的组织如何实现此功能?谢谢!

zz98107 回答:修改REST API响应以仅包括查询参数中请求的字段

方法1:将对象转换为Map,删除多余的键,将Map转换为Json

@GetMapping("/v1/users")
@ResponseBody
public List<Map> getUsers(@RequestParam(required = false) Set<String> fields) { 
    List<User> users = ...;
    ObjectMapper oMapper = new ObjectMapper();
    return users.stream().map(u -> oMapper.convertValue(u,Map.class))
       .peek(map -> { 
          if (fields != null) map.keySet().retainAll(fields)
       })
       .collect(Collectors.toList());
}

方法2:使用Gson

@GetMapping("/v1/users")
@ResponseBody
public String getUsers(@RequestParam(required = false) Set<String> fields) { 
    List<User> users = ...;
    Gson gson = new GsonBuilder()
            .setExclusionStrategies(new ExclusionStrategy() {
                @Override
                public boolean shouldSkipField(FieldAttributes f) {
                    return f.getDeclaringClass().equals(User.class)
                             && fields != null 
                             && !fields.contains(f.getFieldName())
                            ;
                }

                @Override
                public boolean shouldSkipClass(Class<?> clazz) {
                    return false;
                }
            }).create();
    return gson.toJson(users); 
}
  

跨“ https://github.com/monitorjbl/json-view”。但是被团队击落了。

顺便说一句,Jackson支持@JsonView注解,但是它不允许根据需要动态包含/排除字段。您可以定义字段子集,然后返回这些子集

public class Views {
    public static class Short {
    }
}

public class User {
    @JsonView(Views.Short.class)
    public String city;

    @JsonView(Views.Short.class)
    public String name;

    public String phone;

    public String country;
}

@GetMapping("/v1/users")
@ResponseBody
public String getUsers(@RequestParam(required = false) boolean shortView) { 
    List<User> users = ...;
    ObjectMapper mapper = new ObjectMapper();
    if (shortView) mapper = mapper.writerWithView(Views.Short.class);
    return mapper.writeValueAsString(users);
}
,

这是另一种方法:

假设1:我认为最好将控制器的返回类型定义为域对象,并让spring独自处理将其转换为JSON的问题(与@Alexander Pavlov的回答不同)。 IMO对于一般代码的可读性和诸如swagger这样的工具而言,更好 对控制器进行自省,应该知道应该返回什么。

假设2:您的User类中没有基元。

好吧,现在控制器显然调用了一些“服务”来对数据库进行查询,或者一般来说会执行一些逻辑,最终生成用户列表(返回给客户端的列表)。返回对象应该是这样的:

class Users {

     private List<User> data;
}

class User { // + constructors,getters,setters,etc.
   private String name;
   private String city;
   private String phone;
   private String country;    
}

在这种情况下,您可以在服务中将“ null”放置在您不想返回的字段中:

User user = new User("John","LA",null,null); // you only have name and city

现在,您可以将注释@JsonInclude(Include.NON_NULL)放在类User上,这将指示Jackson完全不将具有“ null”值的字段包含到序列化响应中。

如果您希望将此行为全局应用,则可以配置ObjectMapper bean:

 ObjectMapper mapper = new ObjectMapper();
 mapper.setSerializationInclusion(Include.NON_NULL);
本文链接:https://www.f2er.com/3130646.html

大家都在问