問題描述:
今天在做後臺傳數據到前端解析的時候遇到了這個問題。背景介紹下:後臺傳過去json數據是用阿里的fastjson轉換的,調用的是這個方法
String s = JSON.toJSONStringWithDateFormat(o,dateformat,SerializerFeature.WriteDateUseDateFormat);
ServletActionContext.getResponse().getWriter().write(s);
其中dataformat是格式化時間數據的。傳過去的是一個PageBean對象,該對象繼承了Page對象,Page裏面包含list,pageNo,pageSize。前臺在通過data.list準備取出list循環做點事情的時候,發現全是undefined,通過console.log(data.list),發現這個數據竟然是這個東西$ref:
"$.list[0]"。百度搜了下,這裏就是循環引用造成的。問題分析:
循環引用:當一個對象包含另一個對象時,fastjson就會把該對象解析成引用。引用是通過$ref標示的,下面介紹一些引用的描述
- "$ref":".." 上一級
- "$ref":"@" 當前對象,也就是自引用
- "$ref":"$" 根對象
- "$ref":"$.children.0" 基於路徑的引用,相當於 root.getChildren().get(0)
解決方案:
fastjson提供了多種json轉換方案,有興趣的同學可以自己看看源碼,這裏我們可以採用禁止循環引用的方案:
String s = JSON.toJSONStringWithDateFormat(0,"yyyy-MM-dd HH:mm:ss",SerializerFeature.DisableCircularReferenceDetect);
其中:SerializerFeature.DisableCircularReferenceDetect就是禁止循環引用的方案,我們可以通過枚舉類SerializerFeature來查看到底有多少種方式:public enum SerializerFeature {
QuoteFieldNames,
UseSingleQuotes,
WriteMapNullValue,
WriteEnumUsingToString,
UseISO8601DateFormat,
/**
* @since 1.1
*/
WriteNullListAsEmpty,
/**
* @since 1.1
*/
WriteNullStringAsEmpty,
/**
* @since 1.1
*/
WriteNullNumberAsZero,
/**
* @since 1.1
*/
WriteNullBooleanAsFalse,
/**
* @since 1.1
*/
SkipTransientField,
/**
* @since 1.1
*/
SortField,
/**
* @since 1.1.1
*/
@Deprecated
WriteTabAsSpecial,
/**
* @since 1.1.2
*/
PrettyFormat,
/**
* @since 1.1.2
*/
WriteClassName,
/**
* @since 1.1.6
*/
DisableCircularReferenceDetect,
/**
* @since 1.1.9
*/
WriteSlashAsSpecial,
/**
* @since 1.1.10
*/
BrowserCompatible,
/**
* @since 1.1.14
*/
WriteDateUseDateFormat,
/**
* @since 1.1.15
*/
NotWriteRootClassName,
/**
* @since 1.1.19
*/
DisableCheckSpecialChar,
/**
* @since 1.1.35
*/
BeanToArray
;
private SerializerFeature(){
mask = (1 << ordinal());
}
private final int mask;
public final int getMask() {
return mask;
}
public static boolean isEnabled(int features, SerializerFeature feature) {
return (features & feature.getMask()) != 0;
}
public static int config(int features, SerializerFeature feature, boolean state) {
if (state) {
features |= feature.getMask();
} else {
features &= ~feature.getMask();
}
return features;
}
}