使用fastjson的filter機制將String屬性轉成複雜類型

今天遇到一個很棘手的問題,因爲前期設計的失誤,致使了數據庫中的一個字段不得不用json存儲一個很是複雜的對象,前端獲取到複雜對象後利用json序列化成jsonstring後存到db中的字段前端

獲取數據的時候從db中取得該jsonstring字段後反序列化成這個複雜對象後傳給前端,可是因爲這個複雜對象自己利用了list的泛型機制,這樣就致使了db中是一個json array而且用一個string存,前端對象是一個list對象,這樣反序列化的時候就就不能正確反序列化,由於他試圖將一個「[{},{}]」這樣的一個格式的內容轉成list<>。我前後試過Fastjson,Gson和jackson都不能很好轉換java

先把以前失敗的代碼貼一下,相關邏輯已經簡化,PO表示數據庫持久話對象,BO表示前端展現對象,其中有一個List的複雜對象git

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函數測試一下github

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格式爲json

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

第二步,將一個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\"}]"}this

報錯也很直白

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

  1. PropertyPreFilter 根據PropertyName判斷是否序列化
  2. PropertyFilter 根據PropertyName和PropertyValue來判斷是否序列化
  3. NameFilter 修改Key,若是須要修改Key,process返回值則可
  4. ValueFilter 修改Value
  5. BeforeFilter 序列化時在最前添加內容
  6. 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

相關文章
相關標籤/搜索