環境
fastjson 1.2.41
問題說明
FastJson 問題
在json物件中有多個地方參考了相同的物件,在經過幾次轉換轉為json字串的時候會出現占位符,
然后使用fastjson 決議字串也能正確決議,但使用其他json類別庫決議,無法正常還原資料,還是占位符
測驗代碼
/**
* FastJson 問題
* 測驗 JSONArray(幾個元素有關聯,參考了相同得物件) -> 轉為List -> 加入到 JSONObject 中 -> 最后轉為 json 字串 列印的時候(最后一步得時候會出現占位符)
* -> 然后再轉為 JSONObject 的時候,非FastJson決議會出現問題(fastJson 決議正常,但是其他json類別庫處理時,不會對占位符處理,最后直接就原樣的將值決議成占位符)
* 測驗
* testTransfer1 僅僅資料一樣,但是實際上是幾個不同的物件(資料相同,物件不同),經過上述變化,未出現占位符
* testTransfer2 是從某一元素上取得資料(同一個物件,在json物件中,多個地方都有參考)在添加到該jsonArray 上,經過上述變化,會出現占位符
*/
@Test
public void name() {
// testTransfer1();
testTransfer2();
}
private void testTransfer1() {
// [{"one":1,"two":2,"tickets":[{"one":2,"two":3},{"one":3,"two":4}]},{"one":2,"two":3},{"one":3,"two":4}]
String str = "[{\"one\":1,\"two\":2,\"tickets\":[{\"one\":2,\"two\":3},{\"one\":3,\"two\":4}]},{\"one\":2,\"two\":3},{\"one\":3,\"two\":4}]";
JSONArray array = JSON.parseArray(str);
List<Object> objects = array.toJavaList(Object.class);
JSONObject object = new JSONObject();
object.put("list", objects);
System.out.println(object);
// 經過測驗發現如果,不直接用從某個元素中取資料,在添加到該jsonArray 本身,即使他們資料有重合的(資料相同,但不是同一個物件),也不會出現 占位符的現象
}
private void testTransfer2() {
// [{"one":1,"two":2,"tickets":[{"one":2,"two":3},{"one":3,"two":4}]]
String str = "[{\"one\":1,\"two\":2,\"tickets\":[{\"one\":2,\"two\":3},{\"one\":3,\"two\":4}]}]";
JSONArray array = JSON.parseArray(str);
// 這里添加
JSONArray tickets = array.getJSONObject(0).getJSONArray("tickets");
for (int i = 0; i < tickets.size(); i++) {
array.add(tickets.get(i));
}
List<Object> list = array.toJavaList(Object.class);
// 以下代碼說明 FastJson 在之后 轉為 json 字串 ,然后再決議為 json 物件時處理正常(能正常決議)
JSONObject object = new JSONObject();
object.put("list",list);
String jsonStr = object.toJSONString();
System.out.println(jsonStr);
JSONArray list1 = JSON.parseObject(jsonStr).getJSONArray("list");
System.out.println(list1);
// 切換 為 其他 json類別庫處理,例如:jackson
ObjectMapper mapper = new ObjectMapper();
try {
Object o = mapper.readValue(jsonStr, Object.class);
System.out.println(o);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// 內部 從 某一個 元素取出資料,在添加到 jsonArray 上, 經過 上述轉換 (JSONArray(幾個元素有關聯) -> 轉為List -> 加入到 JSONObject 中 -> 轉為 json 字串),最后會變成這樣
// {"list":[{"tickets":[{"one":2,"two":3},{"one":3,"two":4}],"one":1,"two":2},{"$ref":"$.list[0].tickets[0]"},{"$ref":"$.list[0].tickets[1]"}]}
}
解決辦法
- 去除物件的互相參考關系
- "物件 -> json" 和 "json -> 物件" 兩步轉換統一都用fastJson 類別庫處理,
- 禁用FastJson的“回圈參考檢測”特性,- 禁用FastJson的“回圈參考檢測”特性,
參考:https://www.cnblogs.com/zjrodger/p/4630237.html
參考:https://blog.csdn.net/fly910905/article/details/81504388
/**
* 禁用 fastjson 的 回圈參考檢測
* 使用 SerializerFeature.DisableCircularReferenceDetect
*/
private void testTransfer3() {
String str = "[{\"one\":1,\"two\":2,\"tickets\":[{\"one\":2,\"two\":3},{\"one\":3,\"two\":4}]}]";
JSONArray array = JSON.parseArray(str);
// 這里添加
JSONArray tickets = array.getJSONObject(0).getJSONArray("tickets");
for (int i = 0; i < tickets.size(); i++) {
array.add(tickets.get(i));
}
// 全域關閉
// JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
// 該次決議關閉
// 轉為 json 字串的時候,禁用了 fastjson 的 回圈檢測參考特性
String s = array.toJSONString(array, SerializerFeature.DisableCircularReferenceDetect);
// System.out.println(array.toJSONString());
System.out.println(s);
}
說明
由于springboot 默認使用 jackson 處理json 請求,所以需要注意
由于時間問題,這個地方只是發現情況會出現這種問題,至于物件參考會不會出現這種問題,沒有進行實驗,也沒有對fastjson 原始碼進行解讀
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/253396.html
標籤:其他
上一篇:Python爬蟲新手入門教學(七):爬取騰訊視頻彈幕
下一篇:STL_常用的演算法
