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
【参考文章】
https://www.cnblogs.com/dmego/p/9033080.html
https://blog.csdn.net/JLoveforever/article/details/79885485