前言
作為一名后端開(kāi)發(fā)而言肯定會(huì)接觸數(shù)據(jù),把數(shù)據(jù)提供給前端或者把數(shù)據(jù)存儲(chǔ)起來(lái),目前比較火熱的傳輸格式是json,給前端傳json是再常見(jiàn)不過(guò)啦,甚至是往db里面直接存入json。
在java層面來(lái)說(shuō)json只不過(guò)就是一個(gè)字符串而已,json對(duì)我們的意義是把一個(gè)對(duì)象或者map序列化成json字符串。這樣json就可以在進(jìn)行網(wǎng)絡(luò)io了,同樣你把一個(gè)對(duì)象序列化成了一個(gè)json串存入到db,當(dāng)你從db中讀取出來(lái)的時(shí)候,你讀出來(lái)的也是一個(gè)json的字符串,你還需要進(jìn)行反序列化讓它重新變成對(duì)象。
FastJSON就是一個(gè)幫助你序列號(hào)和反序列化java對(duì)象的工具,這里不會(huì)講很高階的用法,只講大家工作中每天都會(huì)使用到的常見(jiàn)用法。這里多說(shuō)一句,大家可能會(huì)看到網(wǎng)上天天說(shuō)FastJSON這不好那不好....我也知道它有漏洞,可是它很快而且很方便,大部分小公司都依然還會(huì)選擇使用FastJSON來(lái)作為序列化工具。
開(kāi)始之前先導(dǎo)包
/*這里查找最新的包
https://mvnrepository.com/artifact/com.alibaba/fastjson
*/
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.57</version>
</dependency>
序列化
如果你不清楚JSON格式的話,在序列化這里我會(huì)簡(jiǎn)單介紹一下JSON的格式,因?yàn)槟惆裫ava對(duì)象變成json后你可以對(duì)比看,json是如何把你的對(duì)象變成字符串存儲(chǔ)的。
-
簡(jiǎn)單介紹FastJSON(下成FJ)
首先FJ有一個(gè)JSON的靜態(tài)工具類,里面都是我們接下來(lái)會(huì)用到的方法。然后FJ也提供一些其他的別名類,例如
JSONObject,JSONArray,看到名字都應(yīng)該能秒懂,一個(gè)操作對(duì)象一個(gè)操作集合的,但是這里面提供的方法JSON這個(gè)靜態(tài)工具類都有。所以大家用哪個(gè)都可以,下面我統(tǒng)一使用JSON類 -
如何使用,序列化就是把一個(gè)對(duì)象變成方便傳輸方便存儲(chǔ)的格式。
JSON.toJSONString(你要放入的對(duì)象)就可以把一個(gè)對(duì)象變成json格式// 把map變成json public class MultiTest { public static void main(String[] args) { // 這里快速生成一個(gè)map Map<String, String> stuMap = MapUtil.builder("name", "小明"). put("gender", "男").build(); // 使用JSON對(duì)這個(gè)map對(duì)象序列化 String stuJson = JSON.toJSONString(stuMap); // 輸出結(jié)果是 {"gender":"男","name":"小明"} System.out.println(stuJson); } }// 把對(duì)象編程json public class MultiTest { @Data @Builder private static class Student { private String name; private String gender; } public static void main(String[] args) { // 這里快速生成一個(gè)map Map<String, String> stuMap = MapUtil.builder("name", "小明"). put("gender", "男").build(); // 使用JSON對(duì)這個(gè)map對(duì)象序列化 String stuJson = JSON.toJSONString(stuMap); // 輸出結(jié)果是 {"gender":"男","name":"小明"} System.out.println(stuJson); } } -
上面這個(gè)例子,可以看到map和實(shí)體類的序列化結(jié)果是一致的,為什么呢,因?yàn)閷?shí)體類和map本質(zhì)上差不多,都是一個(gè)key,一個(gè)value。name是key,小紅是value,gender是key,男是value。
然后我們看序列化后的結(jié)果,
{"gender":"男","name":"小明"}。我們可以格式化一下就變成(網(wǎng)上有很多工具可以美化json,例如www.json.cn){ "gender": "男", "name": "小明" }美化以后,我們看起來(lái)就簡(jiǎn)單多了,首先json的標(biāo)志一個(gè)花括號(hào)包裹{},其次里面存儲(chǔ)的也是鍵值對(duì),鍵值對(duì)里面使用:來(lái)分割,左邊是key,右邊是value。鍵值對(duì)之間使用逗號(hào)分割。這個(gè)你肯定看的名單,但是鍵值對(duì)的value還有瘋狂套娃,里面可能還是json或者是一個(gè)數(shù)組,甚至是一個(gè)json數(shù)組。你可以自己嘗試使用JSON.toJSONString序列號(hào)一些你經(jīng)常使用到的對(duì)象,看看他的結(jié)果是什么樣子的。
反序列化
既然你把我的java對(duì)象變成了json字符串,那肯定有辦法要變回來(lái)并且這個(gè)操作很常見(jiàn)。
-
把json解析成JSONObject對(duì)象-JSON.parseObject(放入json串)
這里解釋一下JSONObject是什么,JSONObject你可以你把它理解成map,他是FJ對(duì)map的實(shí)現(xiàn),如果你沒(méi)有指定把json解析成什么他會(huì)默認(rèn)轉(zhuǎn)成JSONObject對(duì)象。這個(gè)對(duì)象就當(dāng)map使用,用法一樣,下面是例子
public static void main(String[] args) { // 這里快速生成一個(gè)map Map<String, String> stuMap = MapUtil.builder("name", "小明"). put("gender", "男").build(); // 使用JSON對(duì)這個(gè)map對(duì)象序列化 String stuJson = JSON.toJSONString(stuMap); // 把它轉(zhuǎn)成JSONObject JSONObject jsonObj = JSON.parseObject(stuJson); // %s為類c占位符, 顯示后面變量?jī)?nèi)容 System.out.printf("這位同學(xué)的名字是%s,性別是%s%n", jsonObj.get("name"), jsonObj.get("gender")); // 輸出結(jié)果為 這位同學(xué)的名字是小明,性別是男 } -
JSONObject有一些比map好的地方,emmm也不能說(shuō)比map好,所不相同的地方吧。因?yàn)槟惆岩粋€(gè)對(duì)象變成了json,其實(shí)你已經(jīng)丟掉了它的類型,或者說(shuō)我原來(lái)有泛型來(lái)約束,但是不見(jiàn)了,或者就是說(shuō)我原來(lái)Map<String, Object>,你每次從map里面取出元素以后是需要強(qiáng)轉(zhuǎn)一下的。JSONObject它沒(méi)有泛型,但是它每次get都方法幫你去安全的cast轉(zhuǎn)化一下。所以在JSONObject你可以很方便的get出你想要的類型啦
image-20210410162257019<center>JSONObject可以get出的類型</center>
所以剛剛的例子里面的sout里面語(yǔ)句可以寫(xiě)成
// %s為類c占位符, 顯示后面變量?jī)?nèi)容 System.out.printf("這位同學(xué)的名字是%s,性別是%s%n", jsonObj.getString("name"), jsonObj.getString("gender"));
-
把json解析成Map對(duì)象-JSON.parseObject(放入json串, Map.class)
其實(shí)很簡(jiǎn)單,只要在parseObject的括號(hào)里面加入Map.class,指定你要轉(zhuǎn)成map就好了
public static void main(String[] args) { // 這里快速生成一個(gè)map Map<String, String> stuMap = MapUtil.builder("name", "小明"). put("gender", "男").build(); // 使用JSON對(duì)這個(gè)map對(duì)象序列化 String stuJson = JSON.toJSONString(stuMap); // 把它轉(zhuǎn)成JSONObject Map jsonMap = JSON.parseObject(stuJson ,Map.class); // %s為類c占位符, 顯示后面變量?jī)?nèi)容 System.out.printf("這位同學(xué)的名字是%s,性別是%s%n", jsonMap.get("name"), jsonMap.get("gender")); // 輸出結(jié)果為 這位同學(xué)的名字是小明,性別是男 }這里有一個(gè)要注意的,這樣你轉(zhuǎn)出來(lái)是沒(méi)有泛型約束的,是不安全的,或者說(shuō)...是看起來(lái)很丑的(畢竟你會(huì)在意不安全嗎)...我們可以改傳一個(gè)typeReference。大家不用在意是什么道理,這也不是很重要,看不懂也沒(méi)關(guān)系。
public static void main(String[] args) { // 這里快速生成一個(gè)map Map<String, String> stuMap = MapUtil.builder("name", "小明"). put("gender", "男").build(); // 使用JSON對(duì)這個(gè)map對(duì)象序列化 String stuJson = JSON.toJSONString(stuMap); // 把它轉(zhuǎn)成JSONObject Map<String, Object> jsonMap = JSON.parseObject(stuJson, // 把Map和泛型放入這個(gè)reference里面,注意這里是一個(gè)匿名內(nèi)部類 new TypeReference<Map<String, Object>>() {}); // %s為類c占位符, 顯示后面變量?jī)?nèi)容 System.out.printf("這位同學(xué)的名字是%s,性別是%s%n", jsonMap.get("name"), jsonMap.get("gender")); // 輸出結(jié)果為 這位同學(xué)的名字是小明,性別是男 } -
把json解析成Map對(duì)象-JSON.parseObject(放入json串,對(duì)象.class)
public class MultiTest { @Data @Builder private static class Student { private String name; private String gender; } public static void main(String[] args) { // 這里快速生成一個(gè)map Map<String, String> stuMap = MapUtil.builder("name", "小明"). put("gender", "男").build(); // 使用JSON對(duì)這個(gè)map對(duì)象序列化 String stuJson = JSON.toJSONString(stuMap); // 把它轉(zhuǎn)成JSONObject Student stuObj = JSON.parseObject(stuJson, Student.class); // %s為類c占位符, 顯示后面變量?jī)?nèi)容 System.out.printf("這位同學(xué)的名字是%s,性別是%s%n", stuObj.getName(), stuObj.getGender()); // 輸出結(jié)果為 這位同學(xué)的名字是小明,性別是男 } } -
把json解析成JSONArray--JSON.parseArray(放入json串)
這里的JSONArray就類似于Java的list,因?yàn)樗荈J對(duì)List的實(shí)現(xiàn),它也是沒(méi)有泛型的,get的時(shí)候可以指定需要取出來(lái)的類型,這里就不多說(shuō)啦。注意啦,他這個(gè)get()的入?yún)⑹撬饕聵?biāo),這可是list。
public class MultiTest { @Data @Builder private static class Student { private String name; private String gender; } public static void main(String[] args) { // 這里快速生成幾個(gè)Map Map<String, String> stuMap1 = MapUtil.builder("name", "小明"). put("gender", "男").build(); Map<String, String> stuMap2 = MapUtil.builder("name", "小剛"). put("gender", "男").build(); Map<String, String> stuMap3 = MapUtil.builder("name", "小紅"). put("gender", "女").build(); // 把map放到list中 List<Map<String, String>> stuList = Arrays.asList(stuMap1, stuMap2, stuMap3); // 把list序列化成json String stuListJson = JSON.toJSONString(stuList); // 把json反序列化成list JSONArray stuJsonArray = JSON.parseArray(stuListJson); // 0號(hào)元素取出來(lái)變成JSONObject JSONObject stu1 = stuJsonArray.getJSONObject(0); // 1號(hào)元素取出來(lái)變成map,這里也可以使用TypeReference設(shè)置泛型 Map stu2 = stuJsonArray.getObject(1, Map.class); // 甚至可以直接轉(zhuǎn)成實(shí)體類, 畢竟里面的元素也是json啊 Student stu3 = stuJsonArray.getObject(2, Student.class); } } -
把json解析成List-JSON.parseArray(放入json串,list元素類型.class)
這個(gè)一般用的比較多,因?yàn)榭梢灾苯又付ɡ锩娴姆盒?,返回?lái)就幫你轉(zhuǎn)好了
public class MultiTest { @Data @Builder private static class Student { private String name; private String gender; } public static void main(String[] args) { // 這里快速生成幾個(gè)Map Map<String, String> stuMap1 = MapUtil.builder("name", "小明"). put("gender", "男").build(); Map<String, String> stuMap2 = MapUtil.builder("name", "小剛"). put("gender", "男").build(); Map<String, String> stuMap3 = MapUtil.builder("name", "小紅"). put("gender", "女").build(); // 把map放到list中 List<Map<String, String>> stuList = Arrays.asList(stuMap1, stuMap2, stuMap3); // 把list序列化成json String stuListJson = JSON.toJSONString(stuList); // 把json反序列化成list,里面每個(gè)元素都是student List<Student> studentList = JSON.parseArray(stuListJson, Student.class); } }
后言
以上就是比較常見(jiàn)的對(duì)象和json互轉(zhuǎn)的方法,其實(shí)非常家的簡(jiǎn)單其實(shí)沒(méi)幾個(gè),這樣我再來(lái)復(fù)盤(pán)一下
對(duì)象變json JSON.toJSONString(obj)
json變回對(duì)象 JSON.parseObject(json, 你要變成的對(duì)象類型.class)
json變lsit JSON.parseArray(json, list中元素的類型.class)
是不是十分簡(jiǎn)單,其實(shí)規(guī)則就是他們互轉(zhuǎn),F(xiàn)J給我們提供了非常健壯方便的互轉(zhuǎn)方式,可以自己去看看源碼,我怕說(shuō)太多不太常用大家看的不耐煩....祝大家用的愉快~
更多有意思的文章歡迎大家來(lái)我的個(gè)人blog挖掘,點(diǎn)擊這里
