问题描述:
今天在做后台传数据到前端解析的时候遇到了这个问题。背景介绍下:后台传过去json数据是用阿里的fastjson转换的,调用的是这个方法
其中dataformat是格式化时间数据的。传过去的是一个PageBean对象,该对象继承了Page对象,Page里面包含list,pageNo,pageSize。前台在通过data.list准备取出list循环做点事情的时候,发现全是undefined,通过console.log(data.list),发现这个数据竟然是这个东西$ref: "$.list[0]"。百度搜了下,这里就是循环引用造成的。
- String s = JSON.toJSONStringWithDateFormat(o,dateformat,SerializerFeature.WriteDateUseDateFormat);
- ServletActionContext.getResponse().getWriter().write(s);
问题分析:
循环引用:当一个对象包含另一个对象时,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);
- 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;
- }
- }