使用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的复杂对象
写一个main函数测试一下
第一步 将一个BO对象序列化成jsonstring,其中的list对象转成一个jsonstring 并存到DB中这部都是没有问题的
相应的json格式为
{"groupname":"bo_group","users":[{"empid":"0","name":"name0"},{"empid":"1","name":"name1"},{"empid":"2","name":"name2"}]}
第二步,将一个PO对象(从db中取出)序列化成jsonstring,其中的复杂对象是一个jsonarray的字符串,然后反序列化成一个BO对象,这时候就不行了
其中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
那么在处理POjson的时候调用对应的定制valuefilter
这时候返回的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
获取数据的时候从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 使用 string字符串转换成java的各种类型
- JAVA-使用FastJson解析复杂JSON数据
- FastJson解析复杂字符串(string转bean)
- java json转map(复杂混合类型list、map和string)
- Struts(二十一):类型转换与复杂属性、集合属性配合使用
- [原创]java WEB学习笔记68:Struts2 学习之路-- 类型转换与复杂属性配合使用
- 修复fastjson启用WriteClassName时parse原生类型属性错误的bug
- MysqlHelper使用反射机制智能推算数据类型以及属性名称
- 关于数据序列化(5),定制FastJSON序列化(解决Java大Long类型js的Number接收丢失数据的问题,不序列化某些属性)
- FastJson toString过滤指定的对象属性
- 使用Fastjson生成Json字符串少字段属性(数据丢失)
- 使用fastjson key和属性名不一致问题
- fastjson处理复杂类型转换以及特性研究
- 32-35. Struts2_类型转换错误消息的显示和定制&自定义类型转换器&类型转换器与复杂属性&集合协同使用
- 使用Fastjson生成Json字符串少字段属性
- fastJson如何序列化一个包含list对象的Map对象,如Map<String,List<T>>类型的对象
- 在fastjson中使用SimplePropertyPreFilter忽略指定属性
- jQuery怎么操作json对象jsonTest(即json类型的string,但是要先将string转换为json对象),获取对象属性、获取对象数组的某个对象
- 使用Fastjson生成Json字符串少字段属性(数据丢失)
- 使用fastjson出现json中键值与属性名不一致