fastjson使用詳解


一、fastjson介紹

​在前后端數據傳輸交互中,經常會遇到字符串(String)與json,XML等格式相互轉換與解析,其中json以跨語言,跨前后端的優點在開發中被頻繁使用,基本上可以說是標准的數據交換格式。fastjson 是一個java語言編寫的高性能且功能完善的JSON庫,它采用一種“假定有序快速匹配”的算法,把JSON Parse 的性能提升到了極致。它的接口簡單易用,已經被廣泛使用在緩存序列化,協議交互,Web輸出等各種應用場景中。

FastJson是啊里巴巴的的開源庫,用於對JSON格式的數據進行解析和打包。

特點如下:

(1)能夠支持將java bean序列化成JSON字符串,也能夠將JSON字符串反序列化成Java bean。

(2)顧名思義,fastjson操作 JSON的速度是非常快的。

(3)無其他包的依賴。

(4)使用比較方便。

二、fastjson使用

在Maven項目中使用fastjson庫,需要提前在Maven的配置文件中添加此fastjson包的依賴,如pom.xml文件。

添加下面的依賴:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <!--(起碼1.2.48以上)因為這個版本一下存在漏洞-->
    <version>版本根據自己需要</version>
</dependency>

單獨練習使用的話,下載對應的jar導入項目即可.

jar下載地址:fastjson-1.2.58.jar

三、fastjson 常用 API

fastjson API 入口類是com.alibaba.fastjson.JSON,常用的序列化操作都可以在JSON類上的靜態方法直接完成。

public static final Object parse(String text); // 把JSON文本parse為JSONObject或者JSONArray

public static final JSONObject parseObject(String text); // 把JSON文本parse成JSONObject 
    
public static final <T> T parseObject(String text, Class<T> clazz); // 把JSON文本parse為JavaBean 

public static final JSONArray parseArray(String text); // 把JSON文本parse成JSONArray 

public static final <T> List<T> parseArray(String text, Class<T> clazz); //把JSON文本parse成JavaBean集合 

public static final String toJSONString(Object object); // 將JavaBean序列化為JSON文本 

public static final String toJSONString(Object object, boolean prettyFormat); // 將JavaBean序列化為帶格式的JSON文本 

public static final Object toJSON(Object javaObject); //將JavaBean轉換為JSONObject或者JSONArray。

四、fastjson使用演示

測試類准備

User類

public class User {
    private String username;
    private String password;
    public User(){}
    public User(String username,String password){
        this.username = username;
        this.password = password;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User [username=" + username + ", password=" + password + "]";
    }
}

UserGroup類:這里類里面包含User類的集合。

import java.util.ArrayList;
import java.util.List;

public class UserGroup {
    private String name;  
    private List<User> users = new ArrayList<User>();
    public UserGroup(){}
    public UserGroup(String name,List<User> users){
        this.name = name;
        this.users = users;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<User> getUsers() {
        return users;
    }
    public void setUsers(List<User> users) {
        this.users = users;
    }
    @Override
    public String toString() {
        return "UserGroup [name=" + name + ", users=" + users + "]";
    }  
}

1.java類轉換為json字符串

package javabasic.json;

import com.alibaba.fastjson.JSON;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description: fastjson API使用練習
 * @Author: ggf
 * @Date: 2020/01/11
 */
public class FastJsonTest {
    /**
     * java對象轉換為json字符串
     */
    @Test
    public void objToJson() {
        // 簡單對象轉換
        User user = new User("ggf","123456");
        // 調用toJSONString()
        String userJson = JSON.toJSONString(user);
        System.out.println("java類轉換為json串:" + userJson);

        // 集合(List<E>)轉json串
        User user1 = new User("zhangsan", "123456");
        User user2 = new User("lisi", "654321");
        //創建集合存儲對象
        List<User> users = new ArrayList<User>();
        users.add(user1);
        users.add(user2);
        // 調用toJSONString()轉換對象
        String usersjson = JSON.toJSONString(users);
        System.out.println("集合(List<E>)轉json串:" + usersjson);

        // 復雜java類(類中包含集合對象)轉換json串
        UserGroup userGroup = new UserGroup("userGroup", users);
        // 調用toJSONString()轉換對象
        String userGroupJson = JSON.toJSONString(userGroup);
        System.out.println("復雜java類(類中包含集合對象)轉換json串:" + userGroupJson);

    }
}

輸出結果:

java類轉換為json串:{"password":"123456","username":"ggf"}

集合(List<E>)轉json串:[{"password":"123456","username":"zhangsan"},{"password":"654321","username":"lisi"}]

復雜java類(類中包含集合對象)轉換json串:{"name":"userGroup","users":[{"password":"123456","username":"zhangsan"},{"password":"654321","username":"lisi"}]}

2.json字符串轉為java類

package javabasic.json;

import com.alibaba.fastjson.JSON;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description: fastjson API使用練習
 * @Author: ggf
 * @Date: 2020/01/11
 */
public class FastJsonTest {
    /**
     * json字符串轉為java類
     * 注:字符串中使用雙引號需要轉義 (" --> \"),這里使用的是單引號,易讀性會好很多。
     * json串以“{}”包裹,轉換為java類時,使用:parseObject();
     * json串以“[]”包裹,轉換為java類時,使用:parseArray();
     */
    @Test
    public void jsonToObj() {
        /* json字符串轉簡單java對象
         * 字符串:{"password":"123456","username":"dmego"}
         */
        String jsonStr1 = "{'password':'123456','username':'ggf'}";
        // 調用parseObject()
        User user = JSON.parseObject(jsonStr1, User.class);
        System.out.println("json字符串轉簡單java對象:"+user.toString());

        /*
         * json字符串轉List<Object>對象
         * 字符串:[{"password":"123123","username":"zhangsan"},
         *        {"password":"321321","username":"lisi"}]
         */
        String jsonStr2 = "[{'password':'123123','username':'zhangsan'},{'password':'321321','username':'lisi'}]";
        // 調用parseArray()將字符串轉為集合
        List<User> users = JSON.parseArray(jsonStr2, User.class);
        System.out.println("json字符串轉List<Object>對象:"+users.toString());

        /*json字符串轉復雜java對象
         * 字符串:{"name":"userGroup","users":[{"password":"123123","username":"zhangsan"},{"password":"321321","username":"lisi"}]}
         * */
        String jsonStr3 = "{'name':'userGroup','users':[{'password':'123123','username':'zhangsan'},{'password':'321321','username':'lisi'}]}";
        UserGroup userGroup = JSON.parseObject(jsonStr3, UserGroup.class);
        System.out.println("json字符串轉復雜java對象:"+userGroup);
    }
}

輸出結果:

json字符串轉簡單java對象:User [username=ggf, password=123456]
    
json字符串轉List<Object>對象:[User [username=zhangsan, password=123123], User [username=lisi, password=321321]]

json字符串轉復雜java對象:UserGroup [name=userGroup, users=[User [username=zhangsan, password=123123], User [username=lisi, password=321321]]]

五、fastjson實際開發應用

1.對復雜的json串轉為java類

首先有這么一個json字符串,這是一個羊肉湯的菜譜,數據來源於《聚合數據》

{
  "resultcode":"200",
  "reason":"Success",
  "result":{
    "data":[
      {
        "id":"6269",
        "title":"羊肉湯",
        "tags":"增強抵抗力;煮;家常菜;湯;魯菜",
        "imtro":"鄒城人有喝羊湯的習慣,春夏秋冬羊湯館總斷不了食客,春秋天氣候干燥要喝,夏天入伏要喝“伏羊湯”,陰冷的冬季尤其要喝碗羊湯才夠溫暖。以至於邀友喝羊湯成為了禮儀;“二哥,晚上咱們喝羊湯去”。鄒城的羊湯鋪遍地開花,以至於單縣羊湯、滕州羊湯在鄒城都沒有了用武之地。我們這里的羊湯做法是最純的,基本不放煮肉的香料,就用羊骨和羊肉煮成,“肉嫩湯濃”是其特色。 煮羊湯要先煮羊骨,把羊骨斬成大段焯水后放一點羊板油用細火煮,煮到湯白味濃時放入羊肉。羊肉煮到用筷子能輕松插穿時就要撈出,久煮的話羊肉過爛就失去了軟嫩的口感。 碗里放入蔥花或蒜粒,調入精鹽,放入切的薄薄的羊肉片。把燒的滾開的羊湯盛到碗里,灑上香菜,再挖上一匙子香辣的用羊油潑成的辣椒油,一個字“香”!",
        "ingredients":"山羊肉,500g;羊骨,1000g",
        "burden":"生姜,適量;精鹽,適量;香菜,適量;大蔥,適量;辣椒油,適量;羊板油,適量",
        "albums":[
          "http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/t\/7\/6269_379835.jpg"
        ],
        "steps":[
          {
            "img":"http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/s\/63\/6269_95d65e77b58a1b6b.jpg",
            "step":"1.羊脊骨洗凈用刀斬成段。"
          },
          {
            "img":"http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/s\/63\/6269_a8136c10401a1643.jpg",
            "step":"2.煮鍋里倒入清水,放入羊脊骨,羊肉煮開后撈出。"
          },
          {
            "img":"http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/s\/63\/6269_c7b1c9fc85ddc6de.jpg",
            "step":"3.煮鍋里倒入開水,放入羊脊骨生姜塊大火煮開后改小火。"
          },
          {
            "img":"http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/s\/63\/6269_2b284dc30b4f0875.jpg",
            "step":"4.小火煮40分鍾,煮至湯色發白。"
          },
          {
            "img":"http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/s\/63\/6269_c7ade6439eb2db5a.jpg",
            "step":"5.放入羊肉,加入適量的羊板油小火煮30分鍾。"
          },
          {
            "img":"http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/s\/63\/6269_579748e3b0f15963.jpg",
            "step":"6.撈出煮好的羊肉,晾涼后切薄片。"
          },
          {
            "img":"http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/s\/63\/6269_1550e6f127aa1077.jpg",
            "step":"7.碗里放入蔥花,調入精鹽。"
          },
          {
            "img":"http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/s\/63\/6269_a2c965d77b96da70.jpg",
            "step":"8.放入羊肉片,把滾開的羊湯倒入碗里灑上香菜末。"
          },
          {
            "img":"http:\/\/juheimg.oss-cn-hangzhou.aliyuncs.com\/cookbook\/s\/63\/6269_eea9b807d1dc5995.jpg",
            "step":"9.可以根據喜好調入陳醋放入蒜粒,最后調入辣椒油即可。"
          }
        ]
      }
    ],
    "totalNum":"9",
    "pn":0,
    "rn":"1"
  },
  "error_code":0
}

要想解析這種復雜的字符串,把它轉換成java類的話,首先得先定義好與之相符的java POJO 對象,從上面的json字符串組成來看,我們可以拆分出來四個bean:

最外層的響應:ResponseData

返回結果:ResultBean

數據:DataBean

做菜步驟:StepsBean

將拿到的json字符串數據,用GsonFormat工具來生成java類。

GsonFormat工具的使用可參考該文章:https://www.cnblogs.com/1024zy/p/6370305.html

package javabasic.json;

import java.util.List;

/**
 * @Description: 菜譜數據響應體
 * 使用GsonFormat功能生成
 * @Author: ggf
 * @Date: 2020/01/11
 */
public class ResponseData {
    private String resultcode;
    private String reason;
    private ResultBean result;
    private int error_code;

    public String getResultcode() {
        return resultcode;
    }

    public void setResultcode(String resultcode) {
        this.resultcode = resultcode;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public ResultBean getResult() {
        return result;
    }

    public void setResult(ResultBean result) {
        this.result = result;
    }

    public int getError_code() {
        return error_code;
    }

    public void setError_code(int error_code) {
        this.error_code = error_code;
    }

    @Override
    public String toString() {
        return "ResponseData{" +
                "resultcode='" + resultcode + '\'' +
                ", reason='" + reason + '\'' +
                ", result=" + result +
                ", error_code=" + error_code +
                '}';
    }

    public static class ResultBean {

        private String totalNum;
        private int pn;
        private String rn;
        private List<DataBean> data;

        public String getTotalNum() {
            return totalNum;
        }

        public void setTotalNum(String totalNum) {
            this.totalNum = totalNum;
        }

        public int getPn() {
            return pn;
        }

        public void setPn(int pn) {
            this.pn = pn;
        }

        public String getRn() {
            return rn;
        }

        public void setRn(String rn) {
            this.rn = rn;
        }

        public List<DataBean> getData() {
            return data;
        }

        public void setData(List<DataBean> data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return "ResultBean{" +
                    "totalNum='" + totalNum + '\'' +
                    ", pn=" + pn +
                    ", rn='" + rn + '\'' +
                    ", data=" + data +
                    '}';
        }

        public static class DataBean {
        
            private String id;
            private String title;
            private String tags;
            private String imtro;
            private String ingredients;
            private String burden;
            private List<String> albums;
            private List<StepsBean> steps;

            public String getId() {
                return id;
            }

            public void setId(String id) {
                this.id = id;
            }

            public String getTitle() {
                return title;
            }

            public void setTitle(String title) {
                this.title = title;
            }

            public String getTags() {
                return tags;
            }

            public void setTags(String tags) {
                this.tags = tags;
            }

            public String getImtro() {
                return imtro;
            }

            public void setImtro(String imtro) {
                this.imtro = imtro;
            }

            public String getIngredients() {
                return ingredients;
            }

            public void setIngredients(String ingredients) {
                this.ingredients = ingredients;
            }

            public String getBurden() {
                return burden;
            }

            public void setBurden(String burden) {
                this.burden = burden;
            }

            public List<String> getAlbums() {
                return albums;
            }

            public void setAlbums(List<String> albums) {
                this.albums = albums;
            }

            public List<StepsBean> getSteps() {
                return steps;
            }

            public void setSteps(List<StepsBean> steps) {
                this.steps = steps;
            }

            @Override
            public String toString() {
                return "DataBean{" +
                        "id='" + id + '\'' +
                        ", title='" + title + '\'' +
                        ", tags='" + tags + '\'' +
                        ", imtro='" + imtro + '\'' +
                        ", ingredients='" + ingredients + '\'' +
                        ", burden='" + burden + '\'' +
                        ", albums=" + albums +
                        ", steps=" + steps +
                        '}';
            }

            public static class StepsBean {        

                private String img;
                private String step;

                public String getImg() {
                    return img;
                }

                public void setImg(String img) {
                    this.img = img;
                }

                public String getStep() {
                    return step;
                }

                public void setStep(String step) {
                    this.step = step;
                }

                @Override
                public String toString() {
                    return "StepsBean{" +
                            "img='" + img + '\'' +
                            ", step='" + step + '\'' +
                            '}';
                }
            }
        }
    }
}

對應的實體類創建后,接下來就可以使用fastjson中的方法將json串轉換成對象使用了

package javabasic.json;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.IOUtils;
import org.junit.Test;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: fastjson API使用練習
 * @Author: ggf
 * @Date: 2020/01/11
 */
public class FastJsonTest {

    /**
    *將復雜的json串轉換為java類
    */
    @Test
    public void jsonToComplexObj() {
        // 讀取類路徑下的caipu.json文件,這里使用了第三方工具hutool進行讀取json文件
        // 工具類參見:https://hutool.cn/docs/#/
        String jsonStr = FileUtil.readUtf8String("./javabasic/json/caipu.json");
        System.out.println(jsonStr);
        // 轉換為java類
        ResponseData resp = JSON.parseObject(jsonStr, ResponseData.class);
        System.out.println(resp);

        // 通過對象操作數據
        // 獲取響應碼resultcode
        System.out.println(resp.getResultcode());
        // 獲取響應數據
        ResponseData.ResultBean result = resp.getResult();
        System.out.println("result響應數據:" + result);

    }
}

輸出結果


ResponseData{resultcode='200', reason='Success', result=ResultBean{totalNum='9', pn=0, rn='1', data=[DataBean{id='6269', title='羊肉湯', tags='增強抵抗力;煮;家常菜;湯;魯菜', imtro='鄒城人有喝羊湯的習慣,春夏秋冬羊湯館總斷不了食客,春秋天氣候干燥要喝,夏天入伏要喝“伏羊湯”,陰冷的冬季尤其要喝碗羊湯才夠溫暖。以至於邀友喝羊湯成為了禮儀;“二哥,晚上咱們喝羊湯去”。鄒城的羊湯鋪遍地開花,以至於單縣羊湯、滕州羊湯在鄒城都沒有了用武之地。我們這里的羊湯做法是最純的,基本不放煮肉的香料,就用羊骨和羊肉煮成,“肉嫩湯濃”是其特色。 煮羊湯要先煮羊骨,把羊骨斬成大段焯水后放一點羊板油用細火煮,煮到湯白味濃時放入羊肉。羊肉煮到用筷子能輕松插穿時就要撈出,久煮的話羊肉過爛就失去了軟嫩的口感。 碗里放入蔥花或蒜粒,調入精鹽,放入切的薄薄的羊肉片。把燒的滾開的羊湯盛到碗里,灑上香菜,再挖上一匙子香辣的用羊油潑成的辣椒油,一個字“香”!', ingredients='山羊肉,500g;羊骨,1000g', burden='生姜,適量;精鹽,適量;香菜,適量;大蔥,適量;辣椒油,適量;羊板油,適量', albums=[http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/t/7/6269_379835.jpg], steps=[StepsBean{img='http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/s/63/6269_95d65e77b58a1b6b.jpg', step='1.羊脊骨洗凈用刀斬成段。'}, StepsBean{img='http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/s/63/6269_a8136c10401a1643.jpg', step='2.煮鍋里倒入清水,放入羊脊骨,羊肉煮開后撈出。'}, StepsBean{img='http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/s/63/6269_c7b1c9fc85ddc6de.jpg', step='3.煮鍋里倒入開水,放入羊脊骨生姜塊大火煮開后改小火。'}, StepsBean{img='http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/s/63/6269_2b284dc30b4f0875.jpg', step='4.小火煮40分鍾,煮至湯色發白。'}, StepsBean{img='http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/s/63/6269_c7ade6439eb2db5a.jpg', step='5.放入羊肉,加入適量的羊板油小火煮30分鍾。'}, StepsBean{img='http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/s/63/6269_579748e3b0f15963.jpg', step='6.撈出煮好的羊肉,晾涼后切薄片。'}, StepsBean{img='http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/s/63/6269_1550e6f127aa1077.jpg', step='7.碗里放入蔥花,調入精鹽。'}, StepsBean{img='http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/s/63/6269_a2c965d77b96da70.jpg', step='8.放入羊肉片,把滾開的羊湯倒入碗里灑上香菜末。'}, StepsBean{img='http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/s/63/6269_eea9b807d1dc5995.jpg', step='9.可以根據喜好調入陳醋放入蒜粒,最后調入辣椒油即可。'}]}]}, error_code=0}

2.對json串的操作

在實際開發中,我們經常要對接口返回的json數據,進行操作,獲取里面的某些數據。還是以上面的json字符串為例,使用fastjson,對json字符串進行操作。

package javabasic.json;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.IOUtils;
import org.junit.Test;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: fastjson API使用練習
 * @Author: ggf
 * @Date: 2020/01/11
 */
public class FastJsonTest {
    /**
     * 對json串的操作
     */
    @Test
    public void operateJson() {
        // 讀取本地json文本
        String jsonStr = FileUtil.readUtf8String("./javabasic/json/caipu.json");
        // 創建json對象
        JSONObject jsonObj = JSONObject.parseObject(jsonStr);
        // 操作json內容
        // 獲取響應碼resultcode
        System.out.println(jsonObj.get("resultcode"));
        // 獲取響應信息reason
        System.out.println(jsonObj.getString("reason"));
        // 獲取data
        JSONObject resJsonObj = (JSONObject)jsonObj.get("result");
        System.out.println(resJsonObj.getString("data"));

    }

}

輸出結果

200
    
Success
    
[{"albums":["http://juheimg.oss-cn-hangzhou.aliyuncs.com/cookbook/t/7/6269_379835.jpg"],
  .......以下內容省略 
 "}]

六、fastjson漏洞問題

可參考文章:https://www.cnblogs.com/chaos-li/p/11139992.html

真實項目中使用建設使用版本大於:1.2.45

七、fastjson踩坑

序列化的類必須有一個無參構造方法

被序列化的類需要有一個無參的構造方法。否則會報錯
Exception in thread "main" com.alibaba.fastjson.JSONException: default constructor not found. class User

如果你沒有重寫構造方法,那么每個類都自帶一個無參的構造方法,但是如果你重寫了一個有參的構造方法,那么默認的無參構造方法會被覆蓋,這時候就需要你手動寫一個無參的構造方法進去。所以我建議保險起見,需要被json序列化的類最好都手動寫一個無參的構造方法進去。

在低版本中轉換的時候會直接拋以上異常信息(測試版本:fastjson-1.1.12)。但是高版本(fastjson-1.2.58)就不會報錯。
建議在定義javabean時都把無參和有參定義。

【參考文章】

https://www.cnblogs.com/dmego/p/9033080.html
https://blog.csdn.net/zgzczzw/article/details/72330190
https://blog.csdn.net/JLoveforever/article/details/79885485


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM