Json Serialize SerializeFilter 忽略特定属性
key words:Json Serialize jackson fastjson springmvc responsebody lodash
SpringMVC中直接可以返回经过序列化的对象,只需要在Controller上加上 @ResponseBody
例如:
model 代码:
public class A{
private long id;
private String name;
private String avatar;
private int score;
private B b;
//......setter and getter
}
controller代码:
@RequestMapping("/A")
@ResponseBody
public A getModel(){
A a = new A();
a.setName("one");
a.setAvatar("avatar.jpg");
return a;
}
那么在前端请求/A时就会得到:
{id:0,name:"one",avatar:"avatar.jpg",score:0,b:null}
这不是我希望的结果,我希望前端只能拿到它所需要的name 和 avatar。
能想到的解决方案有如下:
1.用mybatis时,每次查询结果数据,用Map来承载,而不是bean,在Controller中也是如此(甚至可以剔除model层)。但这样就要求对数据库表非常了解,而牺牲了很多便利操作(如 增、改操作)
2.返回时,新建ViewModel,用ViewModel来过滤。比较麻烦
3.jackson,@JsonIgnore。不满足要求,需要序列化的Property,并非固定的。这次我要id,name,下次我可能要name,score
4.使用fastjson的SerializeFilter ,具体见这里。还是有点缺陷,遇到多层次引用就不知道怎么办了:List ,A包含B,过滤了A,却暴露了B。(可能是没深入研究。。。。)
@RequestMapping("/A")
@ResponseBody
public String getModel(){
//A a
SimplePropertyPreFilter filter = new SimplePropertyPreFilter(); // 构造方法里,也可以直接传需要序列化的属性名字
filter.getExcludes().add("id");
filter.getExcludes().add("score");
return JSON.toJSONString(a, filter);
}
不知道java里面有没有类似于lodash.js 中的pick函数的方法,可能javascript里面是弱对象,所以实现和效率都不成问题吧。
贴一段代码求java解决方案:
//载入lodash.js
var _ = require('lodash');
ep.all('topics', function (topics) {
topics.forEach(function (topic) {
UserModel.findById(topic.author_id, ep.done(function (author) {
if (mdrender) {
topic.content = renderHelper.markdown(at.linkUsers(topic.content));
}
topic.author = _.pick(author, ['loginname', 'avatar_url']);
ep.emit('author');
}));
});
ep.after('author', topics.length, function () {
topics = topics.map(function (topic) {
return _.pick(topic, ['id', 'author_id', 'tab', 'content', 'title', 'last_reply_at',
'good', 'top', 'reply_count', 'visit_count', 'create_at', 'author']);
});
res.send({data: topics});
});
});