Getting Started with FastJSON Quickly

2019/09/15

Preface

As a backend developer, you’re definitely going to deal with data—either providing it to the frontend or storing it somewhere. Right now, the most popular transfer format is JSON. Sending JSON to the frontend is as common as it gets, and people even store JSON directly in the DB.

From the Java perspective, JSON is just a string. What JSON means to us is: serialize an object or a map into a JSON string. That way, JSON can be sent over network I/O. Similarly, if you serialize an object into a JSON string and store it in the DB, when you read it back, you’re still reading a JSON string—you’ll need to deserialize it to turn it back into an object.

FastJSON is a tool that helps you serialize and deserialize Java objects. I’m not going to cover super advanced usage here—only the common stuff you’ll use every day at work. One more thing: you might see people online saying FastJSON is bad this and bad that… I know it has vulnerabilities, but it’s fast and convenient, and most small companies will still choose FastJSON as their serialization tool.

Before we start, add the dependency:

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

Serialization

  1. If you’re not familiar with the JSON format, I’ll briefly introduce it here in the serialization section. Because once you turn a Java object into JSON, you can compare the result and see how JSON stores your object as a string.

  2. A quick intro to FastJSON (abbreviated as FJ)

    First, FJ provides a static utility class called JSON, which contains the methods we’ll use next. FJ also provides some alias classes like JSONObject and JSONArray. From the names you can probably tell instantly: one is for objects and one is for collections. But the JSON static utility class already provides all the methods you need, so you can use whichever you like. Below I’ll consistently use the JSON class.

  3. How to use it: serialization is turning an object into a format that’s easy to transmit and store.

    JSON.toJSONString(the object you want to put in) converts an object into JSON format.

    // 把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. From the example above, you can see the serialization result for a map and an entity class is the same. Why? Because an entity class and a map are basically similar in nature: both are key-value pairs. name is the key, 小红 is the value; gender is the key, is the value.

    Now look at the serialized result: {"gender":"男","name":"小明"}. If we pretty-print it (there are lots of tools online to format JSON, like www.json.cn), it becomes:

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

    After formatting, it’s much easier to read. First, JSON is wrapped in curly braces {}. Second, it stores key-value pairs inside. Within a key-value pair, : separates them: key on the left, value on the right. Between key-value pairs, they’re separated by commas. This is definitely familiar, but the value can also be nested like crazy—it might itself be JSON, or an array, or even an array of JSON objects. You can try serializing some objects you use often with JSON.toJSONString and see what the result looks like.

Deserialization

Since you turned my Java object into a JSON string, there must be a way to turn it back—and this is super common.

  • Parse JSON into a JSONObject - JSON.parseObject(put in the JSON string)

    Let me explain what JSONObject is. You can think of JSONObject as a map—it’s FJ’s implementation of a map. If you don’t specify what type to parse the JSON into, it will default to a JSONObject. You can use this object like a map; the usage is the same. Example:

        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 has some advantages over a map… hmm, maybe not “better”, just “different”. Because once you turn an object into JSON, you’ve essentially lost its type. Or in other words, you used to have generics constraining it, but now they’re gone. For example, if it was Map<String, Object>, every time you retrieve an element from the map you need to cast it. JSONObject has no generics either, but each get method helps you safely cast/convert. So with JSONObject, you can conveniently get the type you want.

    image-20210410162257019

    Types you can get from JSONObject

    So in the previous example, the sout statement can be written as:

            // %s为类c占位符, 显示后面变量内容
            System.out.printf("这位同学的名字是%s,性别是%s%n",
                    jsonObj.getString("name"),
                    jsonObj.getString("gender"));
    
  • Parse JSON into a Map - JSON.parseObject(put in the JSON string, Map.class)

    This is actually very simple: just add Map.class inside the parentheses of parseObject to specify you want to convert it into a 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"));
            // 输出结果为   这位同学的名字是小明,性别是男
        }
    

    One thing to note here: the result has no generic constraints, so it’s not type-safe—or… it just looks ugly (even if you care about safety). We can instead pass a TypeReference. Don’t worry about the theory behind it; it’s not that important. If you don’t understand it, that’s fine.

        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"));
            // 输出结果为   这位同学的名字是小明,性别是男
        }
    
  • Parse JSON into an object - JSON.parseObject(put in the JSON string, Object.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());
            // 输出结果为   这位同学的名字是小明,性别是男
        }
      
    }
    
  • Parse JSON into a JSONArrayJSON.parseArray(put in the JSON string)

    JSONArray is similar to Java’s List, because it’s FJ’s implementation of List. It also has no generics, and when you get, you can specify the type you want. I won’t go into detail here. One thing to note: the parameter of get() is an index—this is a 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);
      
        }
      
    }
    
  • Parse JSON into a List - JSON.parseArray(put in the JSON string, elementType.class)

    This one is used more often, because you can directly specify the generic type inside, and it will convert it for you.

    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);
      
        }
      
    }
    

Afterword

Above are the most common ways to convert between objects and JSON. Honestly, it’s super simple—there aren’t many methods. Let me recap:

Object to JSON: JSON.toJSONString(obj)

JSON back to object: JSON.parseObject(json, theTypeYouWant.class)

JSON to list: JSON.parseArray(json, elementTypeInList.class)

Pretty simple, right? The rule is basically converting back and forth. FJ provides very robust and convenient conversion methods. You can check the source code yourself—I’m worried if I talk too much about less commonly used stuff, you’ll get bored…. Have fun using it~

All articles in this blog, unless otherwise stated, are licensed under @Oreoft . Please indicate the source when reprinting!

Table of Contents