快速上手FastJSON

前言

作为一名后端开发而言肯定会接触数据,把数据提供给前端或者把数据存储起来,目前比较火热的传输格式是json,给前端传json是再常见不过啦,甚至是往db里面直接存入json。

在java层面来说json只不过就是一个字符串而已,json对我们的意义是把一个对象或者map序列化成json字符串。这样json就可以在进行网络io了,同样你把一个对象序列化成了一个json串存入到db,当你从db中读取出来的时候,你读出来的也是一个json的字符串,你还需要进行反序列化让它重新变成对象。

FastJSON就是一个帮助你序列号和反序列化java对象的工具,这里不会讲很高阶的用法,只讲大家工作中每天都会使用到的常见用法。这里多说一句,大家可能会看到网上天天说FastJSON这不好那不好....我也知道它有漏洞,可是它很快而且很方便,大部分小公司都依然还会选择使用FastJSON来作为序列化工具。

开始之前先导包

/*这里查找最新的包
https://mvnrepository.com/artifact/com.alibaba/fastjson
*/
<dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>fastjson</artifactId>
         <version>1.2.57</version>
</dependency>

序列化

  1. 如果你不清楚JSON格式的话,在序列化这里我会简单介绍一下JSON的格式,因为你把java对象变成json后你可以对比看,json是如何把你的对象变成字符串存储的。

  2. 简单介绍FastJSON(下成FJ)

    首先FJ有一个JSON的静态工具类,里面都是我们接下来会用到的方法。然后FJ也提供一些其他的别名类,例如JSONObjectJSONArray,看到名字都应该能秒懂,一个操作对象一个操作集合的,但是这里面提供的方法JSON这个静态工具类都有。所以大家用哪个都可以,下面我统一使用JSON类

  3. 如何使用,序列化就是把一个对象变成方便传输方便存储的格式。

    JSON.toJSONString(你要放入的对象)就可以把一个对象变成json格式

    // 把map变成json
    public class MultiTest {
        public static void main(String[] args) {
            // 这里快速生成一个map
            Map<String, String> stuMap = MapUtil.builder("name", "小明").
                    put("gender", "男").build();
            // 使用JSON对这个map对象序列化
            String stuJson = JSON.toJSONString(stuMap);
            // 输出结果是 {"gender":"男","name":"小明"}
            System.out.println(stuJson);
        }
    }
    
    // 把对象编程json
    public class MultiTest {
    
        @Data
        @Builder
        private static class Student {
            private String name;
            private String gender;
        }
    
        public static void main(String[] args) {
            // 这里快速生成一个map
            Map<String, String> stuMap = MapUtil.builder("name", "小明").
                    put("gender", "男").build();
            // 使用JSON对这个map对象序列化
            String stuJson = JSON.toJSONString(stuMap);
            // 输出结果是 {"gender":"男","name":"小明"}
            System.out.println(stuJson);
        }
        
    }
    
  4. 上面这个例子,可以看到map和实体类的序列化结果是一致的,为什么呢,因为实体类和map本质上差不多,都是一个key,一个value。name是key,小红是value,gender是key,男是value。

    然后我们看序列化后的结果,{"gender":"男","name":"小明"}。我们可以格式化一下就变成(网上有很多工具可以美化json,例如www.json.cn

    {
        "gender": "男",
        "name": "小明"
    }
    

    美化以后,我们看起来就简单多了,首先json的标志一个花括号包裹{},其次里面存储的也是键值对,键值对里面使用:来分割,左边是key,右边是value。键值对之间使用逗号分割。这个你肯定看的名单,但是键值对的value还有疯狂套娃,里面可能还是json或者是一个数组,甚至是一个json数组。你可以自己尝试使用JSON.toJSONString序列号一些你经常使用到的对象,看看他的结果是什么样子的。

反序列化

既然你把我的java对象变成了json字符串,那肯定有办法要变回来并且这个操作很常见。

  • 把json解析成JSONObject对象-JSON.parseObject(放入json串)

    这里解释一下JSONObject是什么,JSONObject你可以你把它理解成map,他是FJ对map的实现,如果你没有指定把json解析成什么他会默认转成JSONObject对象。这个对象就当map使用,用法一样,下面是例子

        public static void main(String[] args) {
            // 这里快速生成一个map
            Map<String, String> stuMap = MapUtil.builder("name", "小明").
                    put("gender", "男").build();
            // 使用JSON对这个map对象序列化
            String stuJson = JSON.toJSONString(stuMap);
    
            // 把它转成JSONObject
            JSONObject jsonObj = JSON.parseObject(stuJson);
            // %s为类c占位符, 显示后面变量内容
            System.out.printf("这位同学的名字是%s,性别是%s%n",
                    jsonObj.get("name"),
                    jsonObj.get("gender"));
            
            // 输出结果为   这位同学的名字是小明,性别是男
        }
    
  • JSONObject有一些比map好的地方,emmm也不能说比map好,所不相同的地方吧。因为你把一个对象变成了json,其实你已经丢掉了它的类型,或者说我原来有泛型来约束,但是不见了,或者就是说我原来Map<String, Object>,你每次从map里面取出元素以后是需要强转一下的。JSONObject它没有泛型,但是它每次get都方法帮你去安全的cast转化一下。所以在JSONObject你可以很方便的get出你想要的类型啦

    image-20210410162257019

    <center>JSONObject可以get出的类型</center>

    所以刚刚的例子里面的sout里面语句可以写成

            // %s为类c占位符, 显示后面变量内容
            System.out.printf("这位同学的名字是%s,性别是%s%n",
                    jsonObj.getString("name"),
                    jsonObj.getString("gender"));
    
  • 把json解析成Map对象-JSON.parseObject(放入json串, Map.class)

    其实很简单,只要在parseObject的括号里面加入Map.class,指定你要转成map就好了

        public static void main(String[] args) {
            // 这里快速生成一个map
            Map<String, String> stuMap = MapUtil.builder("name", "小明").
                    put("gender", "男").build();
            // 使用JSON对这个map对象序列化
            String stuJson = JSON.toJSONString(stuMap);
    
            // 把它转成JSONObject
            Map jsonMap = JSON.parseObject(stuJson ,Map.class);
            // %s为类c占位符, 显示后面变量内容
            System.out.printf("这位同学的名字是%s,性别是%s%n",
                    jsonMap.get("name"),
                    jsonMap.get("gender"));
            // 输出结果为   这位同学的名字是小明,性别是男
        }
    

    这里有一个要注意的,这样你转出来是没有泛型约束的,是不安全的,或者说...是看起来很丑的(毕竟你会在意不安全吗)...我们可以改传一个typeReference。大家不用在意是什么道理,这也不是很重要,看不懂也没关系。

        public static void main(String[] args) {
            // 这里快速生成一个map
            Map<String, String> stuMap = MapUtil.builder("name", "小明").
                    put("gender", "男").build();
            // 使用JSON对这个map对象序列化
            String stuJson = JSON.toJSONString(stuMap);
    
            // 把它转成JSONObject
            Map<String, Object> jsonMap = JSON.parseObject(stuJson,
                    // 把Map和泛型放入这个reference里面,注意这里是一个匿名内部类
                    new TypeReference<Map<String, Object>>() {});
            // %s为类c占位符, 显示后面变量内容
            System.out.printf("这位同学的名字是%s,性别是%s%n",
                    jsonMap.get("name"),
                    jsonMap.get("gender"));
            // 输出结果为   这位同学的名字是小明,性别是男
        }
    
  • 把json解析成Map对象-JSON.parseObject(放入json串,对象.class)

    public class MultiTest {
    
        @Data
        @Builder
        private static class Student {
            private String name;
            private String gender;
        }
    
        public static void main(String[] args) {
            // 这里快速生成一个map
            Map<String, String> stuMap = MapUtil.builder("name", "小明").
                    put("gender", "男").build();
            // 使用JSON对这个map对象序列化
            String stuJson = JSON.toJSONString(stuMap);
    
            // 把它转成JSONObject
            Student stuObj = JSON.parseObject(stuJson, Student.class);
            // %s为类c占位符, 显示后面变量内容
            System.out.printf("这位同学的名字是%s,性别是%s%n",
                    stuObj.getName(),
                    stuObj.getGender());
            // 输出结果为   这位同学的名字是小明,性别是男
        }
    
    }
    
  • 把json解析成JSONArray--JSON.parseArray(放入json串)

    这里的JSONArray就类似于Java的list,因为它是FJ对List的实现,它也是没有泛型的,get的时候可以指定需要取出来的类型,这里就不多说啦。注意啦,他这个get()的入参是索引下标,这可是list。

    public class MultiTest {
    
        @Data
        @Builder
        private static class Student {
            private String name;
            private String gender;
        }
    
        public static void main(String[] args) {
            // 这里快速生成几个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号元素取出来变成JSONObject
            JSONObject stu1 = stuJsonArray.getJSONObject(0);
            // 1号元素取出来变成map,这里也可以使用TypeReference设置泛型
            Map stu2 = stuJsonArray.getObject(1, Map.class);
            // 甚至可以直接转成实体类, 毕竟里面的元素也是json啊
            Student stu3 = stuJsonArray.getObject(2, Student.class);
    
        }
    
    }
    
  • 把json解析成List-JSON.parseArray(放入json串,list元素类型.class)

    这个一般用的比较多,因为可以直接指定里面的泛型,返回来就帮你转好了

    public class MultiTest {
    
        @Data
        @Builder
        private static class Student {
            private String name;
            private String gender;
        }
    
        public static void main(String[] args) {
            // 这里快速生成几个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,里面每个元素都是student
            List<Student> studentList = JSON.parseArray(stuListJson, Student.class);
    
        }
    
    }
    

后言

以上就是比较常见的对象和json互转的方法,其实非常家的简单其实没几个,这样我再来复盘一下

对象变json JSON.toJSONString(obj)

json变回对象 JSON.parseObject(json, 你要变成的对象类型.class)

json变lsit JSON.parseArray(json, list中元素的类型.class)

是不是十分简单,其实规则就是他们互转,FJ给我们提供了非常健壮方便的互转方式,可以自己去看看源码,我怕说太多不太常用大家看的不耐烦....祝大家用的愉快~

更多有意思的文章欢迎大家来我的个人blog挖掘,点击这里

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容