JSON工具學習記錄--FastJSON迴圈引用問題
JSON工具學習記錄–FastJSON迴圈引用問題
標籤(空格分隔): fastjson
最近基於他人專案做二次開發,遇到了迴圈引用的問題,簡單來說A引用了B,B引用了C,C引用了A,那麼轉換json就會無休止的轉換下去.
更復雜的情況,A中引用了B,B中引用了一個A的集合,比如廣告引用了廣告型別,廣告型別裡面又有該型別下的所屬廣告.
1.構造情景
這種又叫做雙向引用,個人感覺這種設計本身就不是很合理,當然還要看具體使用場景了.
廣告類:
/**
* @author Niu Li
* @date 2016/8/12
*/
public class ADEntity {
private int id;
private String name;
//引用了一個廣告實體類
private ADTypeEntity adTypeEntity;
public ADEntity(int id, String name, ADTypeEntity adTypeEntity) {
this.id = id;
this.name = name;
this.adTypeEntity = adTypeEntity;
}
//省略get和set
}
廣告實體類:
import java.util.List;
/**
* @author Niu Li
* @date 2016/8/12
*/
public class ADTypeEntity {
private int id;
private String name;
//引用了其廣告集合
private List<ADEntity> lists;
//省略get和set
}
測試程式碼:
public class TestApp {
public static void main(String[] args) {
//構造廣告型別
ADTypeEntity adTypeEntity = new ADTypeEntity();
adTypeEntity.setId(1);
adTypeEntity.setName("輪播圖");
//構造廣告
ADEntity entity1 = new ADEntity(1,"圖1",adTypeEntity);
ADEntity entity2 = new ADEntity(2,"圖2",adTypeEntity);
ADEntity entity3 = new ADEntity(3,"圖3",adTypeEntity);
List<ADEntity> lists = new ArrayList<ADEntity>();
lists.add(entity1);
lists.add(entity2);
lists.add(entity3);
//雙向引用
adTypeEntity.setLists(lists);
String result = JSON.toJSONString(entity1);
System.out.println(result);
}
}
結果可以看到雙向引用被替換成$ref
了:
{
"adTypeEntity": {
"id": 1,
"lists": [
{
"$ref": "$"
},
{
"adTypeEntity": {
"$ref": "$.adTypeEntity"
},
"id": 2,
"name": "圖2"
},
{
"adTypeEntity": {
"$ref": "$.adTypeEntity"
},
"id": 3,
"name": "圖3"
}
],
"name": "輪播圖"
},
"id": 1,
"name": "圖1"
}
2.解決辦法
兩種解決辦法就是哪裡有迴圈引用,就過濾掉該欄位.
1.過濾的方式可以使用JSONField註解宣告該欄位不被轉換為json
@JSONField(serialize = false)
private List<ADEntity> lists;
得到結果
{
"adTypeEntity": {
"id": 1,
"name": "輪播圖"
},
"id": 1,
"name": "圖1"
}
2.自定義轉換欄位
SimplePropertyPreFilter filter = new SimplePropertyPreFilter(ADTypeEntity.class,"id","name");
String result = JSON.toJSONString(entity1,filter);
這表明對於ADTypeEntity類只序列化id和name欄位,這樣的話就排除掉list集合引用了,得到的結果和上面一樣.
3.置頂轉換規則多級過濾
fastjson可以實現一些介面指定過濾屬性.過濾本質是fastjson每一次要序列化欄位的時候都會經過Apply方法進行判斷,只有Apply返回true的時候才會序列化,因此就可以根據屬性名來進行自由過濾.
以下實現PropertyPreFilter介面,根據name值來進行排除判定.
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.PropertyPreFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.util.HashMap;
import java.util.Map;
/**
* @date 2016/8/17
*/
public class ComplexPropertyPreFilter implements PropertyPreFilter {
private Map<Class<?>, String[]> includes = new HashMap<>();
private Map<Class<?>, String[]> excludes = new HashMap<>();
static {
//全域性配置關閉迴圈引用檢測
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
}
public ComplexPropertyPreFilter() {
}
public ComplexPropertyPreFilter(Map<Class<?>, String[]> includes) {
super();
this.includes = includes;
}
public boolean apply(JSONSerializer serializer, Object source, String name) {
//物件為空。直接放行
if (source == null) {
return true;
}
// 獲取當前需要序列化的物件的類物件
Class<?> clazz = source.getClass();
// 無需序列的物件、尋找需要過濾的物件,可以提高查詢層級
// 找到不需要的序列化的型別
for (Map.Entry<Class<?>, String[]> item : this.excludes.entrySet()) {
// isAssignableFrom(),用來判斷型別間是否有繼承關係
if (item.getKey().isAssignableFrom(clazz)) {
String[] strs = item.getValue();
// 該型別下 此 name 值無需序列化
if (isHave(strs, name)) {
return false;
}
}
}
// 需要序列的物件集合為空 表示 全部需要序列化
if (this.includes.isEmpty()) {
return true;
}
// 需要序列的物件
// 找到不需要的序列化的型別
for (Map.Entry<Class<?>, String[]> item : this.includes.entrySet()) {
// isAssignableFrom(),用來判斷型別間是否有繼承關係
if (item.getKey().isAssignableFrom(clazz)) {
String[] strs = item.getValue();
// 該型別下 此 name 值無需序列化
if (isHave(strs, name)) {
return true;
}
}
}
return false;
}
/*
* 此方法有兩個引數,第一個是要查詢的字串陣列,第二個是要查詢的字元或字串
*/
public static boolean isHave(String[] strs, String s) {
for (int i = 0; i < strs.length; i++) {
// 迴圈查詢字串陣列中的每個字串中是否包含所有查詢的內容
if (strs[i].equals(s)) {
// 查詢到了就返回真,不在繼續查詢
return true;
}
}
// 沒找到返回false
return false;
}
public Map<Class<?>, String[]> getIncludes() {
return includes;
}
public void setIncludes(Map<Class<?>, String[]> includes) {
this.includes = includes;
}
public Map<Class<?>, String[]> getExcludes() {
return excludes;
}
public void setExcludes(Map<Class<?>, String[]> excludes) {
this.excludes = excludes;
}
}
自己程式碼中用到的過濾
Pageable pageable = new Pageable(page,rows);
Page<Promotion> promotionPages = promotionService.findPage(pageable);
String[] promotionFilters = {"id", "name","title","image","endDate","priceExpression","memberRanks"};
String[] memberFilter = {"id","name"};
String[] pageFilter = {"pageNumber","pageSize","content","total","totalPages"};
Map<Class<?>,String[]> mapFilter = new HashMap<>();
mapFilter.put(Promotion.class,promotionFilters);
mapFilter.put(MemberRank.class,memberFilter);
mapFilter.put(Page.class,pageFilter);
ResultData result = new ResultData.Builder(ResultVo.OK)
.setData(APPJsonUtil.toJsonObject(mapFilter,null,promotionPages))
.builder();
json工具
/**
* 按照指定序列轉換為jsonObject,多級過濾
* @param object
* @return
*/
public static JSONObject toJsonObject(Map<Class<?>, String[]> includes,Map<Class<?>, String[]> excludes, Object object){
ComplexPropertyPreFilter filter = new ComplexPropertyPreFilter();
if (excludes != null) {
filter.setExcludes(excludes);
}
if (includes != null) {
filter.setIncludes(includes);
}
String result = JSON.toJSONString(object, filter);
return JSON.parseObject(result);
}
相關推薦
JSON工具學習記錄--FastJSON迴圈引用問題
JSON工具學習記錄–FastJSON迴圈引用問題 標籤(空格分隔): fastjson 最近基於他人專案做二次開發,遇到了迴圈引用的問題,簡單來說A引用了B,B引用了C,C引用了A,那麼轉換json就會無休止的轉換下去. 更復雜的情況,A中引用了B,
JSON工具學習記錄--FastJSON
最近做專案,總是與json打交道,在用了即可json工具後,個人認為fastJson最好用,很方便,API也清晰可見,所以記錄下使用方法,給需要的人提供幫助.(部分摘抄自網路) 一.API入口 Fastjson API入口類是com.alibaba.fa
centos 下grep工具學習記錄
空白行 標點符號 及其 16進制 查找 快速查找 ... tab 大寫 一、grep工具快速查找表 grep標準正則相關元字符表示及其的含義: 形式 說明 . 這是一個英文的點號。表示匹配任意單個字符; [] 表示匹配指定範圍內的任意單個字符; [^]
Android應用開發------------Json工具類(fastJson和Gson的兩種工具類)
json一般是Android中比較常用的與伺服器互動的資料形式。我們常用的架包來解析json字串有fastjson和gson 分別寫了兩個工具類: fastJson import java.util.ArrayList; import java.util.List;
解決fastjson迴圈引用問題(死迴圈)
在雙向對映的一方向中新增“@JSONField(serialize=false)”。 @JSONField(serialize = false) public java.util.Set<CmsDocReceiveFile> getCmsDocRe
java json工具類(FastJson)
FastJSON是一個很好的java開源json工具類庫,相比其他同類的json類庫,它的速度的確是fast,最快!但是文件做得不好,在應用前不得不親測一些功能。 實際上其他的json處理工具都和它差不多,api也有幾分相似。 一、JSON規範 參
JSON工具類庫: alibaba/fastjson 使用記錄
-c post lin 序列 tro hive 問題 www. .net JSON工具類庫: alibaba/fastjson 使用記錄 一、了解JSON JSON標準規範中文文檔: http://www.json.org/json-zh.html 最佳實踐:http
Swift學習記錄 -- 14.閉包的使用和解決迴圈引用方法
Swift中的閉包 , 幾乎和OC中的block一模一樣 , 我個人又比較偏好block , 所以覺得閉包還是蠻不錯的 . 在迴圈引用問題上 , 解決方案也更加簡潔 // HttpTool類
學習記錄: 安裝配置自動化工具ansible
ansible學習記錄: 安裝配置ansible更新日期: 2016-11-30系統環境 :centos6.5本機ip :192.168.233.123被管理機ip :192.168.233.124—————————————————————————————————————py版本
[轉] 各種Json解析工具比較 - json-lib/Jackson/Gson/FastJson
config 1.2 content pretty 接口實現 turn sso processor true JSON技術的調研報告一 、各個JSON技術的簡介和優劣1.json-libjson-lib最開始的也是應用最廣泛的json解析工具,json-lib 不好的地方確
Linux 學習記錄:七、fdisk 分區工具
net 硬盤 code sta play 交互 技術 無法使用 編碼表 一、fdisk分區工具 fdisk 是來自 IBM 的老牌分區工具,支持絕大多數操作系統,幾乎所有的 Linux 發行版都裝有 fdisk,包括在 Linux 的 resuce 模式下依然能夠使用。
【PyQt5 學習記錄】005:QMainWindow 及狀態欄、菜單欄和工具欄
qt5 open file statusbar ati etc con bubuko import 1 #!/usr/bin/env python 2 3 import sys 4 from PyQt5.QtWidgets import (QApplic
小程式學習記錄:讀取discuz生成的json資料
在discuz後臺資料庫中建表,testjson,並輸入兩條記錄: testjson.php: <?php if(!defined('IN_DISCUZ')) { exit('Access Denied'); } header("Content-Typ
第009講:了不起的分支和迴圈3 | 學習記錄(小甲魚零基礎入門學習Python)
(標答出處: 魚C論壇) 《零基礎入門學習Python》 基礎題: 0、下面的迴圈會列印多少次"I Love FishC"? for i in range(0, 10, 2): print(‘I Love FishC’) (0,2,4,6,8)共5次 1、下面的迴圈會列
第007、008講:了不起的分支迴圈1&2 | 學習記錄(小甲魚零基礎入門學習Python)
(標答出處: 魚C論壇) 《零基礎入門學習Python》 基礎題: if not (money < 100): 上邊這行程式碼相當於? if money >= 100: assert 的作用是什麼? assert斷言是宣告其布林值必須為真的判定,如果發
迴圈引用導致的json序列化失敗
問題 昨天在給系統加日誌後,系統就一直報 Stack Overflow錯誤,找了很久才發現問題,引入的日誌工具使用 gson序列化,而列印的日誌物件裡包含迴圈引用,導致出錯。 簡單復現 /** * C
PyQt5學習記錄(2)---QMainWindow選單欄、狀態列和工具欄
QMainWindow是繼承自QWidget,提供一個應用程式的主視窗。通過QMainWindow你可以新增自己的QToolBars、QDockWidgets、QMenuBar、QStatusBar等。見下圖: 所以如果我們寫程式的話,主視窗一般都是繼承QMainWind
Json資料的重複引用/迴圈引用($ref)
引用符號 引用 描述 "$ref":".." 上一級 "$ref":"@" 當前物件,也就是自引用 "$ref":"$" 根物件
第007、008講:了不起的分支迴圈1&2 | 學習記錄(小甲魚零基礎入門學習Python)
視訊中小甲魚使用 if elif else 在大多數情況下效率要比全部使用 if 要高,但根據一般的統計規律,一個班的成績一般服從正態分佈,也就是說平均成績一般集中在 70~80 分之間,因此根據統計規律,我們還可以改進下程式以提高效率。 題目備忘:按照100分制,90分以上成績為A,80到90為B,60到
【JSON 註解】JSON迴圈引用2----JSON註解@JsonIgnoreProperties+JAVA關鍵字transient+後臺物件與JSON資料的格式互相轉化
接著來說這個JSON迴圈引用的問題: @JsonIgnoreProperties({"hibernateLazyInitializer", "org","roles"}) 在實體類上註解,在使用jackjson 來解析就行 參考下面 關於JSON格式的轉化,其實關