Fastjon2他来了,性能显著提升,还能再战十年

举报
共饮一杯无 发表于 2022/11/28 11:14:06 2022/11/28
【摘要】 概述阿里官方给的定义是,FASTJSON是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。FASTJSON相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。FASTJSON 2.0是FASTJSON项目...

概述

阿里官方给的定义是,FASTJSON是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。
FASTJSON相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。
FASTJSON 2.0是FASTJSON项目的重要升级,目标是为下一个十年提供一个高性能的JSON库,同一套API支持JSON/JSONB两种协议,JSONPath是一等公民,支持全量解析和部分解析,支持Java服务端、客户端Android、大数据场景。

使用

引入Maven依赖

FASTJSON 2.0中,groupId和1.x不一样,是com.alibaba.fastjson2

<dependency>
  <groupId>com.alibaba.fastjson2</groupId>
  <artifactId>fastjson2</artifactId>
  <version>2.0.1</version>
</dependency>

https://repo1.maven.org/maven2/com/alibaba/fastjson2/fastjson2/
2.0之前的FASTJSON坐标如下,最新版本为1.2.79:

<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version> 1.2.79</version>
</dependency>

https://github.com/alibaba/fastjson/releases
💡官方说明:如果原来使用fastjson 1.2.x版本,可以使用兼容包,兼容包不能保证100%兼容,请仔细测试验证,发现问题请及时反馈。兼容包坐标如下:

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>2.0.1</version>
</dependency>

常用类和方法

在fastjson 2.0中,package和1.x不一样,是com.alibaba.fastjson2。如果你之前用的是fastjson1,大多数情况直接更包名就即可。

package com.alibaba.fastjson2;

class JSON {
    // 将字符串解析成JSONObject
    static JSONObject parseObject(String str);
    
    // 将字符串解析成JSONArray
    static JSONArray parseArray(String str);
    
    // 将字符串解析成Java对象
    static T parseObject(byte[] utf8Bytes, Class<T> objectClass);

    // 将Java对象输出成字符串
    static String toJSONString(Object object);
    
    // 将Java对象输出成UT8编码的byte[]
    static byte[] toJSONBytes(Object object);
}

class JSONB {
    // 将jsonb格式的byte[]解析成Java对象
    static T parseObject(byte[] jsonbBytes, Class<T> objectClass);
    
    // 将Java对象输出成jsonb格式的byte[]
    static byte[] toBytes(Object object);
}

class JSONObject {
    Object get(String key);
    int getIntValue(String key);
    Integer getInteger(String key);
    long getLongValue(String key);
    Long getLong(String key);
    T getObject(String key, Class<T> objectClass);
    
    // 将JSONObject对象转换为Java对象
    T toJavaObject(Class<T> objectClass);
}

class JSONArray {
    Object get(int index);
    int getIntValue(int index);
    Integer getInteger(int index);
    long getLongValue(int index);
    Long getLong(int index);
    T getObject(int index, Class<T> objectClass);
}

class JSONPath {
    // 构造JSONPath
    static JSONPath of(String path);

    // 根据path直接解析输入,会部分解析优化,不会全部解析
    Object extract(JSONReader jsonReader);
    
    // 根据path对对象求值
    Object eval(Object rootObject);
}

class JSONReader {
    // 构造基于String输入的JSONReader
    static JSONReader of(String str);
    
    // 构造基于ut8编码byte数组输入的JSONReader
    static JSONReader of(byte[] utf8Bytes);
    
    // 构造基于char[]输入的JSONReader
    static JSONReader of(char[] chars);
    
    // 构造基于json格式byte数组输入的JSONReader
    static JSONReader ofJSONB(byte[] jsonbBytes)
}

常用案例

字符串转JSON对象/JSON数组

对象:

String jsonObjectStr = "{\"id\":\"1\",\"name\":\"张三\"}";
JSONObject jsonObject = JSON.parseObject(jsonObjectStr);
int id = jsonObject.getIntValue("id");
String name = jsonObject.getString("name");

数组对象:

 //普通数组
String str = "[\"id\", 123]";
JSONArray jsonArray1 = JSON.parseArray(str);
String key = jsonArray1.getString(0);
int value = jsonArray1.getIntValue(1);
log.info(key+":"+value);

//数组对象
String jsonArrayObjectStr = "[{\"id\":\"1\",\"name\":\"张三\"},{\"id\":\"2\",\"name\":\"李四\"}]";
JSONArray jsonArray = JSON.parseArray(jsonArrayObjectStr);
JSONObject jsonObject = jsonArray.getJSONObject(1);
int id = jsonObject.getIntValue("id");
String name = jsonObject.getString("name");
log.info(id+" "+name);

JavaBean对象转JSON格式的字符串

User user = new User();
user.setId(1);
user.setName("小詹");
String userStr = JSON.toJSONString(user);
log.info(userStr);

//JSONWriter.Feature.BeanToArray是fastjson2新特性,fastjson1中没有
String toJSONString = JSON.toJSONString(user, JSONWriter.Feature.BeanToArray);
log.info(toJSONString);

//JavaBean对象生成UTF8编码的byte[]
byte[] utf8JSONBytes = JSON.toJSONBytes(user);
log.info(new String(utf8JSONBytes));

@Data
class User{
    private int id;
    private String name;
}

输出如下:

INFO com.zjq.dailyrecord.utils.fastjson.Fastjson2 - {"id":1,"name":"小詹"}
INFO com.zjq.dailyrecord.utils.fastjson.Fastjson2 - [1,"小詹"]
INFO com.zjq.dailyrecord.utils.fastjson.Fastjson2 - {"id":1,"name":"小詹"}

JSON格式的字符串转JavaBean对象

String jsonObjectStr = "{\"id\":\"1\",\"name\":\"张三\"}";
User user = JSON.parseObject(jsonObjectStr, User.class);
log.info(user.toString());

输出如下:

INFO com.zjq.dailyrecord.utils.fastjson.Fastjson2 - Fastjson2.User(id=1, name=张三)

JSON格式的字符串转JavaBean对象数组

String jsonObjectStr = "[{\"id\":\"1\",\"name\":\"小詹\"},{\"id\":\"2\",\"name\":\"zjq\"}]";
List<User> userList = JSON.parseArray(jsonObjectStr, User.class);
log.info(userList.toString());

输出如下:

INFO com.zjq.dailyrecord.utils.fastjson.Fastjson2 - [Fastjson2.User(id=1, name=小詹), Fastjson2.User(id=2, name=zjq)]

Fastjson2相对fastjson1性能提升

比较版本

  • Fastjson 2.0.1
  • Fastjson 1.2.79
  • Jackson 2.12.4

Parse性能比较

测试代码

package com.alibaba.fastjson_perf.eishay;

import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;

public class EishayParse {
    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(EishayParse.class.getName())
                .mode(Mode.Throughput)
                .timeUnit(TimeUnit.MILLISECONDS)
                .forks(1)
                .build();
        new Runner(options).run();
    }
}

场景介绍及结论

  • EishayParseTreeString场景,将String解析成JSONObject/JSONArray或者HashMap/ArrayList。在这个场景,fastjson2表现出了两倍于fastjson1的性能
  • EishayParseString场景,将String反序列化为JavaBean对象,在这个场景fastjson2相对于fastjson1性能提升了30%的性能。
  • EishayParseStringPretty,将格式化带空格和换行符缩进的String反序列化为JavaBean对象,fastjson2在3.44倍于fastjson1。这个场景在fastjson1中是弱项,在fastjson2中采用新解析的算法,性能有了非常大提升。
  • EishayParseUTF8Bytes,将UTF8格式的byte[]反序列化为JavaBean对象。

WriteString

测试代码

package com.alibaba.fastjson_perf.eishay;

import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;

public class EishayWrite {
    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(EishayWrite.class.getName())
                .mode(Mode.Throughput)
                .timeUnit(TimeUnit.MILLISECONDS)
                .forks(1)
                .build();
        new Runner(options).run();
    }
}

场景介绍及结论

  • EishayWriteString场景,将JavaBean对象序列化为字符串。这个场景中,fastjson2比fastjson1和jackson分别有164%和85%的性能提升
  • EishayWriteUTF8Bytes场景,将JavaBean对象序列化为UTF8格式的byte数组。这个场景中,fastjson2比fastjson1和jackson分别有185%和93%的性能提升

来源
https://github.com/alibaba/fastjson/releases
https://github.com/alibaba/fastjson2/releases/tag/2.0.1
https://github.com/alibaba/fastjson2/wiki/fastjson_benchmark

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位大佬指出。
保持热爱,奔赴下一场山海。🏃🏃🏃

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。