• 教你轻松使用Fastjson


    简介

    在前后端数据传输交互中,经常会遇到字符串(String)与Json、XML等格式相互转换与解析,其中json以跨语言,跨前后端的优点在开发中被频繁使用,基本上可以说是标准的数据交换格式。下面我们就来学习一下常用的Fastjson。

    一、Fastjson介绍

    简介

    Fastjson 是阿里巴巴公司开源的一个 Java 语言编写的高性能功能完善的 JSON 库。它采用一种“假定有序快速匹配”的算法,把 JSON Parse 的性能提升到极致,是目前 Java 语言中最快的 JSON 库,并且它不依赖于其它任何库。

    主要特点:

    • 快速 FAST (比其它任何基于 Java 的解析器和生成器更快,包括 jackson)
    • 强大(支持普通 JDK 类包括任意 Java Bean Class、Collection、Map、Date 或 enum)
    • 零依赖(没有依赖其它任何类库除了 JDK)

    二、Fastjson使用

    maven依赖:

    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>fastjsonartifactId>
        
        <version>版本根据自己需要version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    android版本:

    <dependency>
         <groupId>com.alibabagroupId>
         <artifactId>fastjsonartifactId>
         <version>x.x.xx.androidversion>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三、基本用法

    1.JSON

    fastjson 提供了 JSON.parseObject()JSON.toJSONString 两个直接用于解析和生成的方法。前者实现了反序列化,后者实现了序列化。

    public class User {
        public String name;
        public int age;
        public String emailAddress;
    
        // 省略 getter/setter
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    生成 JSON 格式字符串:(Object to JSON-String)

    User user = new User("怪盗tiangeng",23);
    
    String jsonStr = JSON.toJSONString(user);
    
    • 1
    • 2
    • 3

    解析 JSON 格式字符串:(JSON-String to Object)

    注意,需要 User 类有无参的构造方法。

    String jsonString = "{\"name\":\"怪盗tiangeng\",\"age\":23}";
    
    User user = JSON.parseObject(jsonString, User.class);
    
    • 1
    • 2
    • 3

    2.JSONObject

    Java 中,一个Map对象可以等价描述一个 JavaBeanMap 中的每个键值对,对应 JavaBean 中的一个属性。键为属性名,值为属性值。

    JSONObject 就是fastjson专门提供的一个用于这样的使用场景的 Map

    public class JSONObject extends ... implements Map<String, Object>, ... {
      ...
    }
    
    • 1
    • 2
    • 3

    fastJson 提供了 JSON.parseObject()JSON 格式字符串转换成一个JSONObject 对象(本质上,就是转换成一个Map)。

    String jsonString = "{\"name\":\"怪盗tiangeng\",\"age\":23}";
    
    JSONObject map = JSON.parseObject(jsonString);
    
    String val1 = map.getString("name");
    int val2 = map.getIntValue("age");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对于不同类型的各种属性,JSONObject 提供了不同的 getXXX() 方法与之对应。

    3.JSONArray

    反序列化数组形式的 JSON 格式字符串的第三种方案是利用 fastJson 提供的 JSONArray

    public class JSONArray extends ... implements List<Object>, ... {
      ...
    }
    
    • 1
    • 2
    • 3

    从其定义看,JSONArray 本质上也就是一个 List,所以这种方案本质上和之前的第二种方案没太大区别。

    只不过它不需要在最开始提供所要转换的类型,而是通过各种 getXXX() 方法在获取值数据时进行转换。

    JSONArray arr2 = JSON.parseArray(jsonStr);
    
    for (int i = 0; i < arr2.size(); i++) {
        System.out.println(arr2.getObject(i, User.class));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.数组、集合的序列化和反序列化

    数组的序列化很简单,与普通对象类似;

    User[] arr = new User[3];
    arr[0] = new User("tom", 20, "123@qq.com");
    arr[1] = new User("jerry", 19, "456@qq.com");
    arr[2] = new User("bean", 21, null);
    
    String jsonStr = JSON.toJSONString(arr);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    数组的反序列化,有几种方案,其中一种方案与普通对象的反序列化类似,,唯一需要注意的就是填写正确的数组类型:

    User[] arr = JSON.parseObject(jsonStr, User[].class);
    
    for (User user : arr)
         System.out.println(user);
    
    • 1
    • 2
    • 3
    • 4

    鉴于 List 与 数组 有极大地相似性,另一种反序列化数组形式的JSON 字符串的方案是,将其反序列化为对象的链表:

    List<User> list = JSON.parseArray(jsonStr, User.class);
    
    for (User user : list)
        System.out.println(user);
    
    • 1
    • 2
    • 3
    • 4

    5.泛型 和 RESETfull API

    泛型的引入可以减少无关的代码,这在resetful api返回数据时反映得更为清楚,通常 resetful api 接口返回的 JSON 数据为:

    {"status":0,"msg":'...',"data":{...}},
    {"status":0,"msg":'...',"data":[...]},
    
    • 1
    • 2

    status 表示响应状态码,msg 表示状态码配套的信息,而data才是最核心的部分:响应的数据。一般而言,它要么表示返回一个对象,要么表示返回一个对象的集合(数组或 List

    在这里会把这个结果对象定义成泛型类:

    public class Result<T> {
        public int code;
        public String message;
        public T data;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    否则,data 的类型无穷无尽,你就需要为每一种情况定义一种 Result 类。

    那么对于 data 字段,当 T 是 User 时则可以写为 Result,当是个列表的时候为 Result>,其它类型同理(ResultResult>)。

    对此,Json 字符串转对象时,代码自然就类似如下:

    JSONArray list = JSON.parseArray(jsonStr);
    
    for (int i = 0; i < list.size(); i++) {
        Result<User> result = list.getObject(i, Result.class);
        System.out.println(result);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    6.@JSONField 注解:name 属性

    默认/一般情况下,JSON字段中的名字和类的属性名是一致的。但是也有不一致的情况,因为本身驼峰命名法(如 Java)和下划线命名法(如 C)本身就是两大命名规则“流派”。

    对类的属性使用 @JSONField 注解(及其 name 属性),可以重新指定与该属性对应的JSON字符串中的名字。

    @JSONField(name="email_address")
    public String emailAddress
    
    • 1
    • 2

    你甚至可以重新命名为另一个看起来毫不相关的名字:

    @JSONField(name="xxx")
    public String emailAddress;
    
    • 1
    • 2
    String jsonString = "{\"name\":\"怪盗taingeng\",\"age\":23, \"email_address\":\"123456@qq.com\"}";
    User user = JSON.parseObject(jsonString, User.class);
    
    • 1
    • 2

    7.@JSONField 注解:serialzeFeatures 属性

    在将一个对象转换成·JSON 格式字符串时,fastJson 会自动忽略掉其中值为 null 的属性,及不包含在JSON格式为字符串中。

    User user = new User();
    user.setName("tom");
    System.out.println(JSON.toJSONString(user));  // {"name":"tom"}
    
    • 1
    • 2
    • 3

    有时你需要以更完善的形式来表达出这个对象中的所有属性,即便其值为 null

    为此,fastJson 通过 @JSONField 注解的 serialzeFeatures 属性值进行设置:

    @JSONField(serialzeFeatures={SerializerFeature.WriteNullNumberAsZero})
    private Integer age;
    
    @JSONField(serialzeFeatures={SerializerFeature.WriteMapNullValue})
    private String emailAddress;
    
    @JSONField(serialzeFeatures={SerializerFeature.WriteNullStringAsEmpty})
    private List<String> list;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    User user = new User();
    user.setName("tom");
    System.out.println(JSON.toJSONString(user));
    // {"age":0,"emailAddress":null,"list":null,"name":"tom"}
    
    • 1
    • 2
    • 3
    • 4

    8.@JSONField 注解:format 属性

    当所需要序列化和反序列化的对象的属性有 Date 类型时,这里就涉及到 Date 类型的字符串形式的格式问题,为此 @JSONField注解提供了 format 属性用以自定义其字符串格式:

    @JSONField(format="yyyy-MM-dd")
    private Date birthDate;
    
    • 1
    • 2

    使用ISO-8601日期格式:

    @JSONField(serialzeFeatures={SerializerFeature.UseISO8601DateFormat})
    private Date birthDate;
    
    • 1
    • 2

    反序列化能够自动识别如下日期格式:

    • ISO-8601日期格式
    • yyyy-MM-dd
    • yyyy-MM-dd HH:mm:ss
    • yyyy-MM-dd HH:mm:ss.SSS
    • 毫秒数字
    • 毫秒数字字符串
    • .NET JSON日期格式
    • new Date(198293238)

    9.@JSONField 注解:serialize 属性

    标注了 @JSONField(serialize=false) 的属性在序列化成JSON格式字符串的过程中,会被 fastJSON 忽略。无论其是否有值。

    10.循环引用

    fastJson 自动识别循环混用的问题,并将其替换成 $ref 形式。而是不是 StackOverflowError 异常。

    $ref.. 上一级

    $ref@ 当前对象,也就是自引用

    $ref$ 根对象

    $ref$.children.0 基于路径的引用,相当于 `root.getChildren().get(0)

    如果百分百肯定所要序列化的对象不存在循环引用问题,可以在序列化时关闭该检测功能(默认是开启的)。

    JSON.toJSONString(object, SerializerFeature.DisableCircularReferenceDetect);
    
    • 1

    最后

    好了就介绍到这里,还有更多特性下篇文章更新~~~

  • 相关阅读:
    C++ 内存管理 基本部分
    Spring Boot 系列三:如何自定义一个SpringBoot Srarter
    nginx系列第二篇:nginx源码调试
    MySQL优化第二篇
    思迈特软件蝉联IDC中国Fintech 50强,金融科技实力再获认可!
    全球名校AI课程库(28)| MIT麻省理工 · 基因组学机器学习课程『Machine Learning for Genomics』
    信号本无事,庸人自扰之
    Redis的String常用命令
    MySQL学习笔记
    [tjctf 2023] crypto,pwn,rev部分
  • 原文地址:https://blog.csdn.net/weixin_51626435/article/details/126338403