This is the 20th day of my participation in the Genwen Challenge

This article uses JMH to test the performance of several common JSON parsing libraries in Java. Every time on the net to see what others say the performance of such and such library is how good, crushing other libraries. But seeing is believing. Only what you have tested yourself is believing.

JSON is a fairly common data transfer format in both Web and server development, and the performance of JSON parsing constructs is generally not a concern, except in high-performance systems.

At present, there are many kinds of Java open source JSON class libraries. Here, we take four common JSON libraries for performance testing and comparison, and select the most appropriate JSON library according to the test results.

The four JSON libraries are Gson, FastJson, Jackson, jSON-lib.

A simple introduction

Choosing an appropriate JSON library is a matter of consideration:

  • String parsing into JSON performance

  • String parsing into JavaBean performance

  • JavaBean constructs JSON performance

  • Collection constructs JSON performance

  • Ease of use

First, a brief introduction to the identity background of the four class libraries

Gson

Project address: github.com/google/gson

Gson is the most fully functional Json parser. Gson was originally developed by Google for internal needs, but has been used by many companies or users since the first version was publicly released in May 2008. The application of Gson is mainly toJson and fromJson conversion functions, no dependency, no need to exception additional JAR, can run directly on JDK. Before using this object conversion, you need to create the object type and its members to successfully convert the JSON string into the corresponding object. As long as there are get and set methods in the class, Gson can fully implement jSON-to-bean or bean-to-JSON conversion of complex types, and is a magic tool for JSON parsing.

FastJson

Project address: github.com/alibaba/fas…

Fastjson is a high-performance JSON processor written in Java language, developed by Alibaba. No dependencies, no extra JAR exceptions, and the ability to run directly on the JDK. FastJson has some problems converting complex types of beans to Json. The type of reference may appear, leading to Json conversion errors and the need to specify the reference. FastJson uses an original algorithm that makes Parse faster than any OTHER JSON library.

Jackson

Project address: github.com/FasterXML/j…

Jackson is the most widely used Java open source framework for serializing and deserializing JSON. Jackson is one of the most popular JSON parsers in Github, and the default JSON parser for Spring MVC is Jackson.

Jackson had many strengths:

  • Jackson relies on fewer JARS and is easy to use.

  • Jackson parses large JSON files faster than other Java JSON frameworks such as Gson.

  • The Jackson runtime is low in memory footprint and performs well

  • Jackson has a flexible API that can be easily extended and customized.

The latest version is 2.9.4, and Jackson’s core module consists of three parts:

  1. The jackson-core core package, which provides related apis based on “stream mode” parsing, includes JsonPaser and JsonGenerator. The Jackson internal implementation generates and parses JSON using JsonGenerator and JsonParser, the high-performance stream mode API.

  2. Annotations: The Jackson-Annotations package, which provides standard annotations;

  3. The Jackson-Databind data binding package provides apis based on object binding resolution (ObjectMapper) and tree model resolution (JsonNode); The API based on object binding parsing and the API based on tree model parsing rely on the API based on stream pattern parsing.

Why is Jackson’s introduction so long? Because it is also my favorite.

Json-lib

The address of the project: json-lib.sourceforge.net/index.html

Json-lib is one of the most widely used json parsing tools in the world. Json-lib relies on a lot of third-party packages. For complex types of conversion, json-lib also has disadvantages for converting json to beans, such as a list or map set of another class. Json-lib conversion from JSON to bean is problematic. Json-lib does not meet the needs of the Internet in terms of functionality and performance.

Writing performance tests

Next, start writing performance test code for these four libraries.

Adding Maven dependencies

First, of course, I add maven dependencies for all four libraries. To be fair, I use the latest versions of all of them:

<! Json -lib</groupId> <artifactId> Json -lib</artifactId> <version>2.4</version>  <classifier>jdk15</classifier> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> < artifactId > fastjson < / artifactId > < version > 1.2.46 < / version > < / dependency > < the dependency > < the groupId > com. Fasterxml. Jackson. Core < / groupId > < artifactId > Jackson - databind < / artifactId > < version > 2.9.4 < / version > </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> The < version > 2.9.4 < / version > < / dependency >Copy the code

Four library utility classes

FastJsonUtil.java

public class FastJsonUtil { public static String bean2Json(Object obj) { return JSON.toJSONString(obj); } public static <T> T json2Bean(String jsonStr, Class<T> objClass) { return JSON.parseObject(jsonStr, objClass); }}Copy the code

GsonUtil.java

public class GsonUtil { private static Gson gson = new GsonBuilder().create(); public static String bean2Json(Object obj) { return gson.toJson(obj); } public static <T> T json2Bean(String jsonStr, Class<T> objClass) { return gson.fromJson(jsonStr, objClass); } public static String jsonFormatter(String uglyJsonStr) { Gson gson = new GsonBuilder().setPrettyPrinting().create(); JsonParser jp = new JsonParser(); JsonElement je = jp.parse(uglyJsonStr); return gson.toJson(je); }}Copy the code

JacksonUtil.java

public class JacksonUtil { private static ObjectMapper mapper = new ObjectMapper(); public static String bean2Json(Object obj) { try { return mapper.writeValueAsString(obj); } catch (JsonProcessingException e) { e.printStackTrace(); return null; } } public static <T> T json2Bean(String jsonStr, Class<T> objClass) { try { return mapper.readValue(jsonStr, objClass); } catch (IOException e) { e.printStackTrace(); return null; }}}Copy the code

JsonLibUtil.java

public class JsonLibUtil { public static String bean2Json(Object obj) { JSONObject jsonObject = JSONObject.fromObject(obj); return jsonObject.toString(); } @SuppressWarnings("unchecked") public static <T> T json2Bean(String jsonStr, Class<T> objClass) { return (T) JSONObject.toBean(JSONObject.fromObject(jsonStr), objClass); }}Copy the code

Prepare Model class

Here I write a simple Person class with attributes like Date, List, Map, and a custom class FullName to simulate the real world as much as possible.

public class Person { private String name; private FullName fullName; private int age; private Date birthday; private List<String> hobbies; private Map<String, String> clothes; private List<Person> friends; Public String toString() {StringBuilder STR = new StringBuilder("Person [name=" + name + ") ", fullName=" + fullName + ", age=" + age + ", birthday=" + birthday + ", hobbies=" + hobbies + ", clothes=" + clothes + "]\n"); if (friends ! = null) { str.append("Friends:\n"); for (Person f : friends) { str.append("\t").append(f); } } return str.toString(); } } public class FullName { private String firstName; private String middleName; private String lastName; public FullName() { } public FullName(String firstName, String middleName, String lastName) { this.firstName = firstName; this.middleName = middleName; this.lastName = lastName; @override public String toString() {return "[firstName=" + firstName + ", middleName=" + middleName + ", lastName=" + lastName + "]"; }}Copy the code

JSON serialization performance benchmark

@BenchmarkMode(Mode.SingleShotTime) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Benchmark) public class @param ({"1000", "10000", "100000"}) private int count; private Person p; public static void main(String[] args) throws Exception { Options opt = new OptionsBuilder() .include(JsonSerializeBenchmark.class.getSimpleName()) .forks(1) .warmupIterations(0) .build(); Collection<RunResult> results = new Runner(opt).run(); ResultExporter. ExportResult (" JSON serialization performance ", the results, "count", "second"); } @Benchmark public void JsonLib() { for (int i = 0; i < count; i++) { JsonLibUtil.bean2Json(p); } } @Benchmark public void Gson() { for (int i = 0; i < count; i++) { GsonUtil.bean2Json(p); } } @Benchmark public void FastJson() { for (int i = 0; i < count; i++) { FastJsonUtil.bean2Json(p); } } @Benchmark public void Jackson() { for (int i = 0; i < count; i++) { JacksonUtil.bean2Json(p); } } @Setup public void prepare() { List<Person> friends=new ArrayList<Person>(); Friends. Add (createAPerson (" Ming ", null)); friends.add(createAPerson("Tony",null)); Friends.add (createAPerson(null)); P =createAPerson(" 小 时 ",friends); } @TearDown public void shutdown() { } private Person createAPerson(String name,List<Person> friends) { Person newPerson=new Person(); newPerson.setName(name); newPerson.setFullName(new FullName("zjj_first", "zjj_middle", "zjj_last")); newPerson.setAge(24); List<String> hobbies=new ArrayList<String>(); Hobbies. Add (" basketball "); Hobbies. Add (" swimming "); hobbies.add("coding"); newPerson.setHobbies(hobbies); Map<String,String> clothes=new HashMap<String, String>(); clothes.put("coat", "Nike"); clothes.put("trousers", "adidas"); Clothes. Put ("shoes", "anta "); newPerson.setClothes(clothes); newPerson.setFriends(friends); return newPerson; }}Copy the code

Just to illustrate, in the code above

ResultExporter. ExportResult (" JSON serialization performance ", the results, "count", "second");Copy the code

This is a method I wrote to fill the Echarts graph with the performance test report data and export the PNG image.

The result diagram after execution:

As can be seen from the above test results, when the number of serialization times is small, Gson performance is the best. When the number of serialization times increases to 100000, Gson details are weaker than Jackson and FastJson. In this case, FastJson performance is really good. Jackson has been doing well. And that JSON-lib is just for laughs. ^_^

JSON deserialization performance benchmark

@BenchmarkMode(Mode.SingleShotTime) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Benchmark) public class JsonDeserializeBenchmark {/** * deserializeBenchmark */ @param ({"1000", "10000", "100000"}) private int count; private String jsonStr; public static void main(String[] args) throws Exception { Options opt = new OptionsBuilder() .include(JsonDeserializeBenchmark.class.getSimpleName()) .forks(1) .warmupIterations(0) .build(); Collection<RunResult> results = new Runner(opt).run(); ResultExporter. ExportResult (" JSON deserialization performance ", the results, "count", "second"); } @Benchmark public void JsonLib() { for (int i = 0; i < count; i++) { JsonLibUtil.json2Bean(jsonStr, Person.class); } } @Benchmark public void Gson() { for (int i = 0; i < count; i++) { GsonUtil.json2Bean(jsonStr, Person.class); } } @Benchmark public void FastJson() { for (int i = 0; i < count; i++) { FastJsonUtil.json2Bean(jsonStr, Person.class); } } @Benchmark public void Jackson() { for (int i = 0; i < count; i++) { JacksonUtil.json2Bean(jsonStr, Person.class); } } @Setup public void prepare() { JsonStr = "{\" name \ ": \" shao students \ ", \ "fullName \" : {\ "firstName \" : \ "zjj_first \", \ "middleName \" : \ "zjj_middle \", \ "lastName \" : \ "zjj_la St \}, \ "age \" : 24, \ "birthday \ hobbies" : null, \ '\ ": [\" basketball \ ", \ "swimming \", \ "coding \], \" thanks \ ": {\" shoes \ ": \" anta \ ", \ "trousers \" : \ "a Didas \ ", \ "coat Nike \ \", \ "friends"}, \ '\ ": [{\" name \ ": \" xiao Ming \ ", \ "fullName \" : {\ "firstName \" : \ "xxx_first \", \ "middleName \" : \ "xxx_ Middle \ ", \ "lastName \", \ "xxx_last \"}, \ "age \" : 24, \ "birthday \ hobbies" : null, \ '\ ": [\" basketball \ ", \ "swimming \", \ "coding \], \" thanks \ ": {\" s Hoes \ ": \" anta \ ", \ "trousers \", \ "adidas \" and \ "coat Nike \ \", \ ""}, \" friends \ ": null}, {\" name \ ": \" Tony \ ", \ "fullName \" : {\ "firstName \ Xxx_first ": \" \ ", \ "middleName \" : \ "xxx_middle \" and \ "lastName \", \ "xxx_last \"}, \ "age \" : 24, \ "birthday \ hobbies" : null, \ '\ ": [\ basketball \. Swimming ", \ "\", \ "coding \", \ "thanks \" : {\ "shoes \" : \ "anta \", \ "trousers \" : \ "adidas \", \ "coat \" : \ "Nike \}, \" friends \ ": null}, {\" name \ ": \" Chen Xiaoer \ ", \ "fullName \" : {\ "firstName \" : \ "xxx_first \", \ "middleName \" : \ "xxx_middle \", \ "lastName \" : \ "xxx_last \}, \" age: 24, \" Birthday \ \ "", null, \" hobbies \ ": [\" basketball \ ", \ "swimming \", \ "coding \], \" thanks \ ": {\" shoes \ ": \" anta \ ", \ "trousers \" : \ "adidas \", \ "coat \" : \"Nike\"},\"friends\":null}]}"; } @TearDown public void shutdown() { } }Copy the code

The result diagram after execution:

As you can see from the above test results, when deserializing, Gson, Jackson, and FastJson, the performance is pretty good, and jSON-lib is still going to be funny.