I’m sure you’ve all used Gson and FastJSON in your coding to convert Java objects to JSON strings.

This article focuses on the pitfalls and solutions that bloggers encounter when using these two tools at work.

Feel useful can click a like ha ~

1. Introduction

Looked at me in an article published time, already was two months ago, the two months work is very busy, work overtime is also many, spare time to study other technical writing articles (below), the first recorded in the article I this paragraph of time working in the pit, but the main purpose of writing articles is also want to record the problem, Facilitate to help others also facilitate their own later view, nonsense not to say, began to explain the problem ~

2.Gson and Fastjson introduction

Google Gson is a simple Java-based library for serializing Java objects to JSON and vice versa. It is an open source library developed by Google.

Fastjson has the same function as Gson, but it is a tool developed by Domestic Alibaba.

Fastjson is many times faster than Gson, and because it is developed in China, it is widely used, but also frequently exposed problems, and the official has urgently fixed the updated version. But in actual use, these two tools also have their own pits, reasonable according to their own needs to choose tools.

3. Problem explanation and solution

The following will first explain the pit I encountered, and then will give the corresponding solution, of course, you can find a better solution ~

3.1 Gson will convert the Integer type to a Double

Scenario: the editing function of a business requirement, I need to hide the ID obtained after the query on the page, so that I can modify the data according to the ID when saving. However, when I tested myself, I found that the value uploaded to the page was a double type, but the value in the database was an int, which caused the problem that could not be modified. After checking the problems one by one, I found that it was Gson’s fault

Solution 1: Use FastJSON to solve the problem. After introducing dependencies, the code uses the following (recommended) :

Map<String,Object> map = JSONObject.parseObject(result,Map.class);
Copy the code

Solution 2: Change the Integer type of the object to String, so that it is not automatically converted (for your own business)

Workaround 3: Define the type directly when defining Gson as follows:

private static Type typeToken = new TypeToken<TreeMap<String, Object>>(){}.getType();
Gson gson = new GsonBuilder()
            .registerTypeAdapter(
                    new TypeToken<TreeMap<String, Object>>(){}.getType(),
                    new JsonDeserializer<TreeMap<String, Object>>() {
                        @Override
                        public TreeMap<String, Object> deserialize( JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
 
                            TreeMap<String, Object> treeMap = new TreeMap<>();
                            JsonObject jsonObject = json.getAsJsonObject();
                            Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
                            for (Map.Entry<String, JsonElement> entry : entrySet) {
                                Object ot = entry.getValue();
                                if(ot instanceof JsonPrimitive){
                                    treeMap.put(entry.getKey(), ((JsonPrimitive) ot).getAsString());
                                }else{ treeMap.put(entry.getKey(), ot); }}return treeMap;
                        }
                    }).create();
Copy the code

Call in actual code:

Map<String, Object> params = gson.fromJson(result, typeToken);
Copy the code

3.2 Gson does not serialize anonymous inner classes

Scenario: Write a test class to test the interface when completing the task interface, initialize the Map set in the following elegant way:

Map<String, String> map = new HashMap<String, String>() {
    {
	put("logNo"."123456");
        put("reqTime"."20210607"); }}; Gson gson =new Gson();
System.out.println(gson.toJson(map));
Copy the code

However, if you run the test class, the output will be null. This is because the Map generated in this way is an instance of an anonymous inner class, that is, the new Map does not have a class name.

An adapter for an inner class generates an implicit reference to an external class/instance, leading to a circular reference. So the conclusion is: Gson does not serialize anonymous inner classes.

Workaround: With FastJSON, this problem does not occur and can be successfully serialized to JSON data

If you think that fastjson can solve all the problems in Gson, let’s take a look at fastjson in practice.

3.3 Fastjson changes the order of data

Scenario: Encryption, decryption, and signature verification are required for interconnection with other company interfaces to prevent data from being tampered during transmission for security purposes. In this case, the order of the data transmitted by JSON is important. If the data is scrambled, the decryption check will fail. I had this problem when USING Fastjson and had a headache

Solution 1: Add parameters without adjusting the order when parsing returned data (recommended)

At this point your Fastjson version should be 1.2.3 or higher

	<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.23.</version>
        </dependency>
Copy the code

Add the Feature.OrderedField parameter when parsing the data

FrontJsonResponse frontJsonResponse = JSONObject.parseObject(response,FrontJsonResponse.class, Feature.OrderedField);
Copy the code

Solution 2: Use Gson to parse the data without changing the data order

Gson gson = newGson (); FrontJsonResponse frontJsonResponse = gson.fromJson(response,FrontJsonResponse.class)Copy the code

3.4 Fastjson changes the first letter of a field to lowercase

Scenario: If you want to serialize an object entity (FILE_NM, etc.), using FastJSON will change the first letter of each attribute in the entity to lowercase (e.g. FILE_NM), this will definitely cause problems, you can use the following method to solve:

Solution 1: Annotate the attribute name with @jsonField (name = “”) (recommended)

@JSONField(name = "FILE_NM")
private String FILE_NM;
Copy the code

Solution 2: Add the new PascalNameFilter() argument to serialization, which forces the first letter to uppercase.

JSON.toJSONString(bean,new PascalNameFilter());
Copy the code

3.5 FastJSON does not convert multiple layers of JSON to a Map

Scenario: During the interface verification of a third-party company, fastjson is used to convert returned data to a Map, and the verification fails when the string verification to be signed is generated. The query results show that the string verification is inconsistent with the string verification generated by the third-party company because the processing methods are different. For details, see the following example:

    public static void main(String[] args) {
        String str = "{\"result\":{\"user_info\":{\"id\":14390753,\"sex\":1},\"complete_status\":0},\"errcode\":0}";
        Map<String,Object> fastMap = JSONObject.parseObject(str, Map.class);
        System.out.println("fastMap====="+fastMap);
        Gson gson = new Gson();
        Map<String,Object> gsonMap = gson.fromJson(str,Map.class);
        System.out.println("gsonMap====="+gsonMap);
    }
Copy the code

The output result of the above code is:

fastMap====={result={"user_info": {"sex":1."id":14390753},"complete_status":0}, errcode=0}
gsonMap====={result={user_info={id=1.4390753 e7, sex=1.0}, complete_status=0.0}, errcode=0.0}
Copy the code

Comparing the processing with the actual result, you can see that if there are multiple layers of JSON objects in a JSON string, FastJSON does not process the inner layer of JSON, only the outer layer of JSON data is converted to a Map, whereas Gson converts all jSON-formatted data to a Map.

Finally, after confirming with the third party, because they have different processing methods in different interfaces, we can only be compatible (because they can not change, for fear of affecting other users). According to different interfaces, we can decide whether to use FastJSON or Gson to parse the returned data and then check it (really… It’s a long story…

So, in this case, we have to decide what the other side is going to do, and then we have to decide what the connection is going to be, which is one of the differences between the two tools.

4. To summarize

Above problems in the actual development process is very headache, if you don’t step by step, the debug code output, do not think of is the problem that the json conversion tool, but two tools do each have each advantage, I think is the best way to choose to suit their own business code, these problems can be solved, also is not in, or go to a solution, I keep a record of all the problems I encounter so I can solve them directly in the future, which is also good.