您的位置:首页 > Web前端 > JavaScript

使用fastjson的filter机制将String属性转成复杂类型

2018-01-23 14:10 513 查看
今天遇到一个很棘手的问题,由于前期设计的失误,导致了数据库中的一个字段不得不用json存储一个非常复杂的对象,前端获取到复杂对象后利用json序列化成jsonstring后存到db中的字段

获取数据的时候从db中取得该jsonstring字段后反序列化成这个复杂对象后传给前端,但是由于这个复杂对象本身利用了list的泛型机制,这样就导致了db中是一个json array并且用一个string存,前端对象是一个list对象,这样反序列化的时候就就不能正确反序列化,因为他试图将一个“[{},{}]”这样的一个格式的内容转成list<>。我先后试过Fastjson,Gson和jackson都不能很好转换

先把之前失败的代码贴一下,相关逻辑已经简化,PO表示数据库持久话对象,BO表示前端展示对象,其中有一个List的复杂对象

class User{
private String name;
private String empid;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmpid() {
return empid;
}

public void setEmpid(String empid) {
this.empid = empid;
}
}

class GroupBO{
private String groupname;
private List<User> users;

public String getGroupname() {
return groupname;
}

public void setGroupname(String groupname) {
this.groupname = groupname;
}

public List<User> getUsers() {
return users;
}

public void setUsers(List<User> users) {
this.users = users;
}
}

class GroupPO {
private String groupname;
private String users;

public String getGroupname() {
return groupname;
}

public void setGroupname(String groupname) {
this.groupname = groupname;
}

public String getUsers() {
return users;
}

public void setUsers(String users) {
this.users = users;
}
}


写一个main函数测试一下

public static void main(String[] args) throws IOException {
//构建VO
List<User> users=new ArrayList<User>();
for(int i=0;i<3;i++){
User u=new User();
u.setName("name"+i);
u.setEmpid(String.valueOf(i));
users.add(u);
}
GroupBO groupBO=new GroupBO();
groupBO.setGroupname("bo_group");
groupBO.setUsers(users);
String bojson=JSON.toJSONString(groupBO);
GroupPO groupPOFromJsonString=JSON.parseObject(bojson,GroupPO.class);
//构建PO
GroupPO groupPO=new GroupPO();
groupPO.setGroupname("po_group");
groupPO.setUsers("[{\"empid\":\"0\",\"name\":\"name0\"},{\"empid\":\"1\",\"name\":\"name1\"},{\"empid\":\"2\",\"name\":\"name2\"}]");
String pojson=JSON.toJSONString(groupPO);
GroupBO groupBOFromJsonString=JSON.parseObject(pojson,GroupBO.class);
System.out.println("end");
}

第一步 将一个BO对象序列化成jsonstring,其中的list对象转成一个jsonstring 并存到DB中这部都是没有问题的

GroupPO groupPOFromJsonString=JSON.parseObject(bojson,GroupPO.class);

相应的json格式为

{"groupname":"bo_group","users":[{"empid":"0","name":"name0"},{"empid":"1","name":"name1"},{"empid":"2","name":"name2"}]}

第二步,将一个PO对象(从db中取出)序列化成jsonstring,其中的复杂对象是一个jsonarray的字符串,然后反序列化成一个BO对象,这时候就不行了

GroupBO groupBOFromJsonString=JSON.parseObject(pojson,GroupBO.class);

其中json为

{"groupname":"po_group","users":"[{\"empid\":\"0\",\"name\":\"name0\"},{\"empid\":\"1\",\"name\":\"name1\"},{\"empid\":\"2\",\"name\":\"name2\"}]"}

报错也很直白

com.alibaba.fastjson.JSONException: syntax error, expect {, actual string, pos 32, fastjson-version 1.2.44

这时候就要想办法把其中json的user部分由一个字符串包起来的jsonarray转成一个标准的json array

所以这时候就要利用上fastjson中提供一个filter机制在转jsonstring的时候额外处理一下,对于fastjson来说有几个标准的filter,你可以基于其中filter实现自己的filter 参考 https://github.com/alibaba/fastjson/wiki/SerializeFilter
PropertyPreFilter 根据PropertyName判断是否序列化

PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化

NameFilter 修改Key,如果需要修改Key,process返回值则可

ValueFilter 修改Value

BeforeFilter 序列化时在最前添加内容

AfterFilter 序列化时在最后添加内容

由于是POtoBO的时候,PO中的jsonstirng的value部分序列化不对,所以我们可以定制一个简单的valuefilter来处理对应的jsonstring

class MyToBOFilter implements ValueFilter {
@Override
public Object process(Object object, String propertyName, Object propertyValue) {
try {
if(propertyName.equals(GroupPO.class.getDeclaredField("users").getName())){
return JSON.parse(String.valueOf(propertyValue));
}else{
return propertyValue;
}
} catch (NoSuchFieldException e) {
return propertyValue;
}
}
}

那么在处理POjson的时候调用对应的定制valuefilter

public static void main(String[] args) throws IOException {
//构建VO
List<User> users=new ArrayList<User>();
for(int i=0;i<3;i++){
User u=new User();
u.setName("name"+i);
u.setEmpid(String.valueOf(i));
users.add(u);
}
GroupBO groupBO=new GroupBO();
groupBO.setGroupname("bo_group");
groupBO.setUsers(users);
String bojson=JSON.toJSONString(groupBO);
GroupPO groupPOFromJsonString=JSON.parseObject(bojson,GroupPO.class);
//构建PO
GroupPO groupPO=new GroupPO();
groupPO.setGroupname("po_group");
groupPO.setUsers("[{\"empid\":\"0\",\"name\":\"name0\"},{\"empid\":\"1\",\"name\":\"name1\"},{\"empid\":\"2\",\"name\":\"name2\"}]");
String pojson=JSON.toJSONString(groupPO,new MyToPOFilter());
GroupBO groupBOFromJsonString=JSON.parseObject(pojson,GroupBO.class);
System.out.println("end");
}

这时候返回的json为,并且json也可以争取的反序列化成对应的对象了

{"groupname":"po_group","users":[{"empid":"0","name":"name0"},{"empid":"1","name":"name1"},{"empid":"2","name":"name2"}]}

当然在BO转PO的时候你也可以定制自己的valuefilter实现某些前端类型对应DB的字段的逻辑

另外在定制序列化的时候也可以使用pasreprocess来定制,具体可以参考 https://github.com/alibaba/fastjson/wiki/%E5%AE%9A%E5%88%B6%E5%BA%8F%E5%88%97%E5%8C%96 https://github.com/alibaba/fastjson/wiki/ParseProcess
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  fastjson
相关文章推荐