由于项目是RESTful风格设计,前后端采用接口访问的形式,进行数据交流。
所以会涉及到json转换的问题。
1、转换前过滤
即在序列化实体的时候,就已经通过注释,取消了需要过滤的字段的序列化步骤。
简单点说,就是生成实体的时候,就过滤掉需要过滤的字段。
下面两个都是Jackson的注解。
@JsonIgnoreProperties注解在类上
//生成json时将name和age属性过滤
@JsonIgnoreProperties({"name"},{"age"})
public class user {
private String name;
private int age;
private String sex;
}
@JsonIgnore 和上面的注解功能一样,不过是注解地方是在属性上面
public class user {
private String name;
private int age;
@JsonIgnore //生成json时将sex属性过滤
private String sex;
}
优点:方便快捷,针对性强,操作性少,耦合性低。
缺点:硬编码,被注解的参数,无法再序列化(再也查询不到了),不是动态的。
2、选择性转换(侧面过滤)
@JsonView是jackson json中的一个注解,Spring webmvc也支持这个注解。
主要原理是:通过定义两个不同场景的json视图,在转换json格式的时候,选择不同的视图转换,以达到过滤字段的效果。
public class User {
public interface WithoutPasswordView {};
public interface WithPasswordView extends WithoutPasswordView {};
private String username;
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
@JsonView(WithoutPasswordView.class)
public String getUsername() {
return this.username;
}
@JsonView(WithPasswordView.class)
public String getPassword() {
return this.password;
}
}
在这个对象中定义了两个接口,其中WithoutPasswordView指的就是不带密码的视图,WithPasswordView指的是带密码的视图,并且继承了WithoutPasswordView的视图。
测试:
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
//创建对象
User user = new User("isea533","123456");
//序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
objectMapper.writerWithView(User.WithoutPasswordView.class).writeValue(bos, user);
System.out.println(bos.toString());
bos.reset();
objectMapper.writerWithView(User.WithPasswordView.class).writeValue(bos, user);
System.out.println(bos.toString());
}
优点:半灵活,新思路。
缺点:增加了很多不必要的结构。不太建议使用。
选择这个方法的童鞋,请多查阅资料,确定影响和优劣。
此栗子调用:http://blog.csdn.net/isea533/article/details/40428179
3、转换中过滤
工具类在json转换中,通过转换过程中的判断,除去不需要的字段。
Gson:http://blog.csdn.net/binghongchazuoan/article/details/52058275一个Demo,没有试过,因为我测试的项目,不是使用这个的。
fastJSON的PropertyFilter:
List models=new ArrayList<>();
for(int i=0;i<11;i++){
Users model=new Users();
model.setAge(i);
model.setName("liu");
models.add(model);
}
PropertyFilter profilter = new PropertyFilter(){
@Override
public boolean apply(Object object, String name, Object value) {
// 过滤年龄大于5的,也就是说,在这里,自定义规则过滤
if(name.equalsIgnoreCase("age")&&value.equals(5)){
return false;
}
return true;
}
};
OkhttpUtils.println(JSON.toJSONString(models, profilter));
来自http://blog.csdn.net/qingfeng812/article/details/73332034的栗子
json-lib的JsonConfig
JsonConfig jc=newJsonConfig();
// 使用setExcludes方法过滤,例如我不想要对象中的roleinfo和departmentInfo:
jc.setExcludes(newString[]{"roleinfo","departmentInfo"});
// 最后转换出来的字符串就会过滤掉我们不要的属性。
JSONArray.fromObject(list,jc).toString();
最后一种,是通过java自定义注解,加上json的过滤功能,达到很灵活的过滤方式。本质上,还是上面三种方式。
栗子:http://www.jb51.net/article/105633.htm
4、转换后过滤
网友想出的奇思妙想,通过对json字符串的解析,用纯java代码,加json的remove方法,除去指定的参数:
栗子:http://blog.csdn.net/dudufine/article/details/52218463
总结:每个方式都有优缺点,具体选择还是看项目和需求吧。然后说个痛苦的事情,就是我们项目是使用Jersey中的最简单的实体自动转换json,无法过滤。。。。源码是说Jersey是使用的fastJSON去转换的,但是,没有找到解决方法。然后,我们的解决方案就是,封装实体,啊哈,这个肯定很死,不过架构这么说,我也没办法啦啦啦
2020年3月20日更新
当初年轻,现在发现,针对不同的接口定义不同的response是最优解,也是很多公司项目结构的现成方案。数据可以用查出的数据gatset(框架有工具类或者自己写)到response里面。