问题:
场景1:使用fastJson将对象转换成字符串,发现转换后的字符串中包含 $ref字符
场景2:后端返回前端的json串中包含 $ref字符
其实上述两种场景是同一个原因,后端返回到前端的json串是使用@ResponseBody注解,该方式本质上也是json序列化。所以只要解决场景1的问题,就解决了该问题。
实体类:
class Car{
private String name;
private String color;
public Car(String name, String color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
public static void main(String[] args) {
Map<String, Car> map = new HashMap<>();
Car car = new Car("奥迪", "black");
map.put("1", car);
map.put("2", car);
System.out.println(JSONObject.toJSONString(map));
}
序列化后的字符串为:{“1”:{“color”:“black”,“name”:“奥迪”},“2”:{"
r
e
f
"
:
"
ref":"
ref":".1"}}
由于map中的两个value使用一个对象引用,而序列化的时候这个对象只会被序列化一次,其他指向该引用的地方就会转换成 “$ref”,name这种情况应该怎样解决呢?
解决:
fastJson中的toJSONString方法在序列化的时候可以指定序列化策略SerializerFeature:
public static final String toJSONString(Object object, SerializerFeature... features) {
SerializeWriter out = new SerializeWriter();
try {
JSONSerializer serializer = new JSONSerializer(out);
for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
serializer.config(feature, true);
}
serializer.write(object);
return out.toString();
} finally {
out.close();
}
}
其中DisableCircularReferenceDetect代表代表消除对同一对象循环引用的问题,默认为false。指定该序列化策略再尝试一次:
public static void main(String[] args) {
Map<String, Car> map = new HashMap<>();
Car car = new Car("奥迪", "black");
map.put("1", car);
map.put("2", car);
System.out.println(JSONObject.toJSONString(map, SerializerFeature.DisableCircularReferenceDetect));
}
输出结果为:{“1”:{“color”:“black”,“name”:“奥迪”},“2”:{“color”:“black”,“name”:“奥迪”}}。我们可以看到对象中存个多个引用也会正常序列化。
注意:
该策略默认为false,主要是为了解决json序列化的循环引用问题的(循环引用即A中包含B,B中又包含了A,这样在序列化你过程中会进入死循环),所以在使用该策略的时候,要注意是否存在循环依赖的情况。