解决FastJson中"$ref重复引用"的问题方法

解决FastJson中"$ref重复引用"的问题,先来看一个例子吧:

public static void main(String[] args) {
 UserGroup userGroup = new UserGroup().setName("UserGroup");

 User user = new User("User");
 for (int i = 0; i < 3; i++) {
  userGroup.addUser(user);
 }
 Console.log(JSON.toJSONString(userGroup));
}

@Data
@AllArgsConstructor
static class User {
 private String name;
}

@Data
@Accessors(chain = true)
static class UserGroup {
 private String name;
 private List<User> users = Lists.newArrayList();

 public UserGroup addUser(User user) {
  this.getUsers().add(user);
  return this;
 }
}

输出结果:

{"name":"UserGroup","users":[{"name":"User"},{"$ref":"$.users[0]"},{"$ref":"$.users[0]"}]}

<!--- more --->

上面的现象就是将user对象的引用重复使用造成了重复引用问题,Fastjson默认开启引用检测将相同的对象写成引用的形式:

{"$ref": "$"} // 引用根对象
{"$ref":"@"} // 引用自己
{"$ref":".."} // 引用父对象
{"$ref":"../.."} // 引用父对象的父对象
{"$ref":"$.members[0].reportTo"} // 基于路径的引用

目前来说,前端还没有一个很好的办法来解析这样的JSON格式。

除了上面的重复引用外, 还衍生出了另外一个概念:"循环引用",下面来看下两者之间的区别吧:

  • 重复引用:指一个对象引用重复出现多次
  • 循环引用:对象A引用对象B,对象B引用对象A(这种情况一般是个雷区,轻易不要尝试的好,很容易引发StackOverflowError)

再来看一个循环引用的例子:

public static void main(String[] args) {
 Order order = new Order().setName("Order");
 Item item = new Item().setName("Item");

 item.setOrder(order);
 order.setItem(item);

 Console.log(JSON.toJSONString(order));
 Console.log("----------------------------");
 Console.log(JSON.toJSONString(item));
}

@Data
@Accessors(chain = true)
static class Order {
 private String name;
 private Item item;
}

@Data
@Accessors(chain = true)
static class Item {
 private String name;
 private Order order;
}

{"item":{"name":"Item","order":{"$ref":".."}},"name":"Order"}
----------------------------
{"name":"Item","order":{"item":{"$ref":".."},"name":"Order"}}

解决方案

关闭FastJson引用检测机制(慎用,循环引用时可能导致StackOverflowError)

JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect)

避免循环引用(某一方的引用字段不参与序列化:@JSONField(serialize=false))

避免一个对象引用被重复使用多次(使用拷贝的对象副本来完成JSON数据填充)

public static void main(String[] args) {
 UserGroup userGroup = new UserGroup().setName("UserGroup");

 User user = new User("User");
 for (int i = 0; i < 3; i++) {
  User duplicateUser = new User();
  BeanUtil.copyProperties(user, duplicateUser);
  userGroup.addUser(duplicateUser);
 }
 Console.log(JSON.toJSONString(userGroup));
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • FastJson对于JSON格式字符串、JSON对象及JavaBean之间的相互转换操作

    fastJson对于json格式字符串的解析主要用到了一下三个类: JSON:fastJson的解析器,用于JSON格式字符串与JSON对象及javaBean之间的转换. JSONObject:fastJson提供的json对象. JSONArray:fastJson提供json数组对象. 我们可以把JSONObject当成一个Map<String,Object>来看,只是JSONObject提供了更为丰富便捷的方法,方便我们对于对象属性的操作.我们看一下源码. 同样我们可以把JSONArra

  • fastjson 使用方法详细介绍

    Fastjson介绍 Fastjson是一个Java语言编写的JSON处理器. 1.遵循http://json.org标准,为其官方网站收录的参考实现之一. 2.功能qiang打,支持JDK的各种类型,包括基本的JavaBean.Collection.Map.Date.Enum.泛型. 3.无依赖,不需要例外额外的jar,能够直接跑在JDK上. 4.开源,使用Apache License 2.0协议开源.http://code.alibabatech.com/wiki/display/FastJ

  • fastjson生成json时Null属性不显示的解决方法

    举个例子 Map < String , Object > jsonMap = new HashMap< String , Object>(); jsonMap.put("a",1); jsonMap.put("b",""); jsonMap.put("c",null); jsonMap.put("d","wuzhuti.cn"); String str = JSO

  • Spring MVC+FastJson+hibernate-validator整合的完整实例教程

    一:hibernate-validator 基础 1. 简介: 通过使用注解Annotations 给类或者类的属性加上约束(constraint),在运行期检查属性值的合法性. 2. 作用: 在API接口开发中参数校验是非常重要的事情,因为客户端很可能会少传参数,或者值不合法,甚至参数值是恶意的,所以对客户端传来的参数的合法性就必须要校验了,其中将参数值的校验规则通过注解的形式注解到属性上是一种比较优雅的方式. 3. 常用的约束注解 @Null 被注释的元素必须为 null @NotNull

  • SpringBoot Redis配置Fastjson进行序列化和反序列化实现

    FastJson是阿里开源的一个高性能的JSON框架,FastJson数据处理速度快,无论序列化(把JavaBean对象转化成Json格式的字符串)和反序列化(把JSON格式的字符串转化为Java Bean对象),都是当之无愧的fast:功能强大(支持普通JDK类,包括javaBean, Collection, Date 或者enum):零依赖(没有依赖其他的任何类库). 1.写一个自定义序列化类 /** * 自定义序列化类 * @param <T> */ public class FastJ

  • 例举fastJson和jackson转json的区别

    首先举个fastJson和jackson转json的例子,然后对比两种的区别 例子1: { "statusCode": 800, "returnObj": { "hzOrderId": 14, "orderId": 2015111311521900000, "orderSendPlanId": 67 } } 1.jackson-ObjectMapper转json 上面是一个json字符串,有两层,一层是最外

  • springMVC利用FastJson接口返回json数据相关配置详解

    一直使用的是FastJson,感觉还不错,很方便.看了一段别人的分析,觉得很有道理. 为什么要使用Fastjson,其实原因不需要太多,喜欢就行. 我之所以要替换掉Jackson最主要的原因是Jackson在处理对象之前的循环嵌套关系时不便. ps:什么是对象间的循环嵌套?比如A有一个List,B对象里又有一个A对象,当然返回A对象的Json字符串时,如果是 Jackson就会发生异常,因为Jackson天生不具备处理这种关系的能力,而Fastjson正好具备了这种能力(另,如果你用的是 Jac

  • SpringBoot整合FastJson过程解析

    这篇文章主要介绍了SpringBoot整合FastJson过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.Maven依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.33</version> </dependency&

  • 解决FastJson中"$ref重复引用"的问题方法

    解决FastJson中"$ref重复引用"的问题,先来看一个例子吧: public static void main(String[] args) { UserGroup userGroup = new UserGroup().setName("UserGroup"); User user = new User("User"); for (int i = 0; i < 3; i++) { userGroup.addUser(user); }

  • 详解在springmvc中解决FastJson循环引用的问题

    我们先来看一个例子: package com.elong.bms; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import com.alibaba.fastjson.JSON; public class Test { public static void main(String[] args) { Map<String, Student> maps = new HashMap<

  • 解决fastjson泛型转换报错的解决方法

    错误信息 Exception in thread "main" java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.xh.demo.UserDO 泛性类 @Data public class ResultSetDTO<T> { private Integer totalSize; private Integer count; private List<T

  • vue在同一个页面重复引用相同组件如何区分二者

    目录 同一个页面重复引用相同组件如何区分二者 1.使用情境 2.解决方法 在同一个页面重复引用相同组件时的干扰处理 同一个页面重复引用相同组件如何区分二者 1.使用情境 我在同一个vue中引用了同样的一个图层选择的组件,需要区分二者的选择的radio值,如果不做区分,这二者选择的radio值看上去将会一样 2.解决方法 先说原理,这个重复引用的组件虽然一样,但是二者在被创建的时候各自走了一遍生命周期,所以变量之间不冲突. 首先在引用组件中新增一个props,这里命名为spareId,用来区分二者

  • Vue混合文件使用以及ref的引用实例详解

    目录 mixin混合 前言 ref的引用DOM ref引用组件 mixin混合 在日常开发中,当我们开发的各种组件可能会有相同的内容,我们可以将相同的内容在各个相对应的组件内删除,然后放在同一个配置里.所谓混合:两个或多个组件共享一个配置.当然这个配置文件的名字可以自定义,为了具体语义化,我将这个文件名命名mixin,当然看个人喜好. 配置混合文件 mixin.js ,为了加深了解,继续在混合文件上添加data数据以及添加原组件data数据 // mixin.js export const mi

  • 完美解决thinkphp唯一索引重复时出错的问题

    比如如下字段(g_check_id):唯一索引 如果插入数据时(g_check_id)出现相同的值的话,程序本身是会报错的. 所以做类似如下处理: 以上这篇完美解决thinkphp唯一索引重复时出错的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • 解决php表单重复提交实现方法

    重复提交是我们开发中会常碰到的一个问题,除了我们使用js来防止表单的重复提交,同时还可以使用php来防止重复提交哦. <?php /* * php中如何防止表单的重复提交 */ session_start(); if (empty($_SESSION['ip'])) {//第一次写入操作,判断是否记录了IP地址,以此知道是否要写入数据库 $_SESSION['ip'] = $_SERVER['REMOTE_ADDR']; //第一次写入,为后面刷新或后退的判断做个铺垫 //...........

  • 解决vuejs项目里css引用背景图片不能显示的问题

    解决:build->utils.js里,修改:增加 publicPath:'../../', if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, publicPath:'../../', fallback: 'vue-style-loader' }) } else { return ['vue-style-loader'].concat(loaders) } 以上这篇解决vuejs项目里css引用背景图片

  • Django 解决distinct无法去除重复数据的问题

    今天需要使用Django查询一列的字段(不含重复),搞了一上午,发现这样的事情:如图: 得到的数据几乎是相等的,没有区别. 但是仔细看会发现:下面的数据比起上面的还是少了一个. 解决办法: django的distinct在使用之前必须先使用order_by方法排序,如图: 这样就完美解决了这个问题. 补充知识:Distinct和Group by去除重复字段记录 重复记录 有两个意义,一是完全重复的记录,也即所有字段均重复的记录 二是部分关键字段重复的记录,比如Name字段重复,而其他字段不一定重

  • 解决vue2.0 element-ui中el-upload的before-upload方法返回false时submit()不生效问题

    我要实现的功能是在上传文件之前校验是否表格中存在重复的数据,有的话,需要弹窗提示是否覆盖,确认之后继续上传,取消之后,就不再上传. 项目中用的element-ui是V1.4.3 <el-upload class="upload-demo" drag ref="fileUpload" :action="urls.fileUpload" :on-success="handleUploadSuccess" :on-error=

随机推荐