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

简介: 阿里官方给的定义是,FASTJSON是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。

概述

阿里官方给的定义是,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性能比较

测试代码

https://github.com/alibaba/fastjson2/blob/2.0.1/core/src/test/java/com/alibaba/fastjson_perf/eishay/EishayParse.java

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

测试代码

https://github.com/alibaba/fastjson2/blob/2.0.1/core/src/test/java/com/alibaba/fastjson_perf/eishay/EishayWrite.java

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

相关文章
|
JSON 算法 安全
不破不立!Fastjson2.0 性能炸裂,为了下一个十年
Alibaba Fastjson: 目前在人类已知范围内,这个星球跑的最快的Java JSON库。在过去的十年里,fastjson v1作为国内github star最多和最受欢迎的json解析库,如今fastjson v2 重磅来袭,性能炸裂。
18980 2
不破不立!Fastjson2.0 性能炸裂,为了下一个十年
|
Java
Java中的抽象类:深入了解抽象类的概念和用法
Java中的抽象类是一种不能实例化的特殊类,常作为其他类的父类模板,定义子类行为和属性。抽象类包含抽象方法(无实现)和非抽象方法。定义抽象类用`abstract`关键字,子类继承并实现抽象方法。抽象类适用于定义通用模板、复用代码和强制子类实现特定方法。优点是提供抽象模板和代码复用,缺点是限制继承灵活性和增加类复杂性。与接口相比,抽象类可包含成员变量和单继承。使用时注意设计合理的抽象类结构,谨慎使用抽象方法,并遵循命名规范。抽象类是提高代码质量的重要工具。
604 1
|
存储 Oracle 安全
JDK 11 是发布了,但收费吗?
自 9 月 26 日,Oracle JDK 11 正式版本发布以来,一直被大家所看好,因为它是继 6、7、8之后,第一个长期支持的版本「见下图」,而 9 、10 估计多半会夭折了。。。
6828 0
JDK 11 是发布了,但收费吗?
|
SQL Java 关系型数据库
MyBatis-Plus 分页魅力绽放!紧跟技术热点,带你领略数据分页的高效与便捷
【8月更文挑战第29天】在 Java 开发中,数据处理至关重要,尤其在大量数据查询与展示时,分页功能尤为重要。MyBatis-Plus 作为一款强大的持久层框架,提供了便捷高效的分页解决方案。通过封装数据库分页查询语句,开发者能轻松实现分页功能。在实际应用中,只需创建 `Page` 对象并设置页码和每页条数,再通过 `QueryWrapper` 构建查询条件,调用 `selectPage` 方法即可完成分页查询。MyBatis-Plus 不仅生成分页 SQL 语句,还自动处理参数合法性检查,并支持条件查询和排序等功能,极大地提升了系统性能和稳定性。
478 0
|
JSON fastjson Java
Spring Boot Jackson 和Fast JSON 用哪个好啊 ?
【4月更文挑战第22天】
3057 1
|
移动开发 网络协议 算法
(十)Netty进阶篇:漫谈网络粘包、半包问题、解码器与长连接、心跳机制实战
在前面关于《Netty入门篇》的文章中,咱们已经初步对Netty这个著名的网络框架有了认知,本章的目的则是承接上文,再对Netty中的一些进阶知识进行阐述,毕竟前面的内容中,仅阐述了一些Netty的核心组件,想要真正掌握Netty框架,对于它我们应该具备更为全面的认知。
824 2
|
运维 监控 Java
实战总结|系统日志规范及最佳实践
打印日志是一门艺术,日志信息是开发人员排查线上问题最主要的手段之一,但规范打日志被开发同学经常所忽视。日志就像保险,平时正常的时候用不上,但是一旦出问题就都想看有没有保险可以用。一条良好的日志,是我们向外部证明的材料。
|
Java 关系型数据库 MySQL
基于SpringBoot后端实现连接MySQL数据库并存贮数据
基于SpringBoot后端实现连接MySQL数据库并存贮数据
|
存储 消息中间件 缓存
本地缓存之王,Caffeine保姆级教程
本地缓存之王,Caffeine保姆级教程
10452 1