快速上手FastJSON

前言

作為一名后端開(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>

序列化

  1. 如果你不清楚JSON格式的話,在序列化這里我會(huì)簡(jiǎn)單介紹一下JSON的格式,因?yàn)槟惆裫ava對(duì)象變成json后你可以對(duì)比看,json是如何把你的對(duì)象變成字符串存儲(chǔ)的。

  2. 簡(jiǎn)單介紹FastJSON(下成FJ)

    首先FJ有一個(gè)JSON的靜態(tài)工具類,里面都是我們接下來(lái)會(huì)用到的方法。然后FJ也提供一些其他的別名類,例如JSONObjectJSONArray,看到名字都應(yīng)該能秒懂,一個(gè)操作對(duì)象一個(gè)操作集合的,但是這里面提供的方法JSON這個(gè)靜態(tài)工具類都有。所以大家用哪個(gè)都可以,下面我統(tǒng)一使用JSON類

  3. 如何使用,序列化就是把一個(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);
        }
        
    }
    
  4. 上面這個(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)擊這里

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容