The problem

The order is lost when Linkedhashmap is used to store an ordered map data structure, and FastJSON is used to convert it to A JSON string and back.

Code examples:

Insertion of sequential code is not guaranteed

import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import java.util.LinkedHashMap; import java.util.Map; public class Main { public static void main(String[] args) { LinkedHashMap<Integer, String> map = new LinkedHashMap<>();  map.put(1, "A"); map.put(3, "A"); map.put(8, "A"); map.put(5, "A"); // Primitive order system.out. println(" primitive order :"); for (Object o : map.entrySet()) { System.out.printf("%s ", o); } //fastjson String fJson = JSON.toJSONString(map); Map m = JSONObject.parseObject(fJson, Map.class); System.out.println(); System.out.println("fastjson:"); for (Object o : m.entrySet()) { System.out.printf("%s ", o); }}}Copy the code

Output:

Original order: 1=A 3=A 8=A 5=A Fastjson: 1=A 8=A 5=A 3=ACopy the code

The reason:

The problem is with the json.parseObject () method of Fastjson. The debug code goes to the following section (version 1.1.23):

com.alibaba.fastjson.JSONObject#JSONObject()

    public JSONObject() {
        this(16, false);
    }
Copy the code

com.alibaba.fastjson.JSONObject#JSONObject(int, boolean)

public JSONObject(int initialCapacity, boolean ordered) { if (ordered) { this.map = new LinkedHashMap(initialCapacity); } else { this.map = new AntiCollisionHashMap(initialCapacity); }}Copy the code

Given that the default ordered = false, we return an AntiCollisionHashMap object of type, and then use that object for put assignment. The map returned does not guarantee the desired order.

See Fastjson Issue: github.com/alibaba/fas…

The solution

Method 1: Use gson to convert the JSON string to a map

Gson implementation:

import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.util.LinkedHashMap; import java.util.Map; public class Main { public static void main(String[] args) { LinkedHashMap<Integer, String> map = new LinkedHashMap<>();  map.put(1, "A"); map.put(3, "A"); map.put(8, "A"); map.put(5, "A"); // Primitive order system.out. println(" primitive order :"); for (Object o : map.entrySet()) { System.out.printf("%s ", o); } //gson Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create(); String gJson = gson.toJson(map); Map m = gson.fromJson(gJson, Map.class); System.out.println(); System.out.println("gson:"); for (Object o : m.entrySet()) { System.out.printf("%s ", o); }}}Copy the code

The output

1=A 3=A 8=A 5=A Gson: 1=A 3=A 8=A 5=ACopy the code

Method 2: Upgrade fastJSON version above 1.2.3 and specify the feature. OrderedField parameter

Code examples:

//fastjson
String fJson = JSON.toJSONString(map);
Map m = JSON.parseObject(fJson, Feature.OrderedField);
System.out.println();
System.out.println("fastjson:");
for (Object o : m.entrySet()) {
    System.out.printf("%s ", o);
}
Copy the code

The output

Original order: 1=A 3=A 8=A 5=A Fastjson: 1=A 3=A 8=A 5=ACopy the code

Principle: According to json.parseObject (fJson, feature.orderedField), the passed feature. OrderedField will be ordered=true, so that the returned map object is of type LinkedHashMap. When you put it, you guarantee the order of the keys.

com.alibaba.fastjson.JSONObject#JSONObject(int, boolean)

public JSONObject(int initialCapacity, boolean ordered) { if (ordered) { this.map = new LinkedHashMap(initialCapacity); } else { this.map = new HashMap(initialCapacity); }}Copy the code

Reference:

Cloud.tencent.com/developer/a… www.cnblogs.com/hujiapeng/p…