关于FastJson出现对象引用问题的解决方案

这里首先说一下后台返回的json格式

总结了一下,大概就是两种:

对象 -----{"key"  , "value"} 对象类型

集合-----{"key"  , "value"} ,{"key"  , "value"} ]数组/集合类型 

注意:在json转换中 对象即Map , Map 即对象 ; 换言而止 , Map 和对象类型转换出来的json字符串格式是一样的;

下面是一个demo演示一下

    @Test
    public void MapToJson(){
        //map类型
        Map map = new HashMap();
        map.put("username" , "东方月初");
        map.put("password" , "123456");
        System.out.println(JSON.toJSONString(map));

        //对象类型
        User user = new User();
        user.setUsername("东方月初");
        user.setPassword("123456");
        System.out.println(JSON.toJSONString(user));
    }

打印结果截图

当前除了这两种 , 还有以各种复杂的格式就是 对象中包含 集合 , 集合中包含对象的混合类型json串, 原理大概差不多 ,这里就不多做解释


接下来进入正题

在有时候,业务逻辑复杂的时候 , 返回的json字符串中可能会出现对象引用的问题, 什么是对象引用呢, 这里简单的做一下演示

首先模拟一个json对象引用的情况

 @Test
    public void jsonTest(){
        //对象类型
        User user = new User();
        user.setUsername("东方月初");
        user.setPassword("123456");

        List<User> userList = new ArrayList<User>();
        //存储两个相同的对象
        userList.add(user);
        userList.add(user);
        System.out.println(JSON.toJSONString(userList));//打印结果[{"password":"123456","username":"东方月初"},{"$ref":"$[0]"}]
        /*
            [{"password":"123456","username":"东方月初"},{"$ref":"$[0]"}]
            {"$ref":"$[0]"}
            $ref -----链接地址
            $[0] -----list集合的索引值
            这里因为list集合中的第二个对象的key 和value 域第一个对象的key和value完全一样 , 所以会出现这种情况
            可以把他理解为系统简写了第二个对象

            在业务逻辑比较复杂的情况下,后台有时候会出现这种对象引用的问题 , 可是这个json串传送给前端页面后 , 前端页面不会识别 ,

         */

解决方案

关闭toJSONString转换json过程中的循环引用

这里是toJSONString的一个构造方法

public static String toJSONString(Object object, SerializerFeature... features) {
    return toJSONString(object, DEFAULT_GENERATE_FEATURE, features);
}

参数2 SerializerFeature 中有一个属性DisableCircularReferenceDetect

作用为关闭循环应用 , 默认情况下为开启

修改上面代码中的参数

 System.out.println(JSON.toJSONString(userList , SerializerFeature.DisableCircularReferenceDetect));

打印结果如下:

[{“password”:“123456”,“username”:“东方月初”},{“password”:“123456”,“username”:“东方月初”}]

关闭循环应用有一个缺点就是 , 在更复杂的json情况加 , 比如

 @Test
    public void jsonTest(){
        //对象类型
        User userA = new User();
        userA.setUsername("东方月初");
        userA.setPassword("123456");

        User userB = new User();
        userB.setUsername("涂山红红");
        userB.setPassword("123456");

        Role role = new Role();
        //role中添加user对象
        role.setRoleName("盟主");
        role.getUserList().add(userA);
        role.getUserList().add(userB);

        userA.getRoleList().add(role);

        //解析user对象的时候 , user对象中包含List<Role> 集合 , 解析role对象的时候 , role对象中有List<User> 集合 , 会陷入死循环状态
        System.out.println(JSON.toJSONString(userA , SerializerFeature.DisableCircularReferenceDetect));

在转换userA的时候 , 由于userA中包含了role , role 中包含了user 这种情况 , 在解析的时候会出现死循环的情况 , 造成堆栈溢出 错误

以上代码运行结果

java.lang.StackOverflowError

at com.alibaba.fastjson.serializer.SerializeWriter.writeFieldValueStringWithDoubleQuoteCheck(SerializeWriter.java:1885)

at com.alibaba.fastjson.serializer.ASMSerializer_1_User.writeDirectNonContext(Unknown Source)

at com.alibaba.fastjson.serializer.ASMSerializer_2_Role.writeDirectNonContext(Unknown Source)

at com.alibaba.fastjson.serializer.ASMSerializer_1_User.writeDirectNonContext(Unknown Source)

解决方案:

在toJSONString的参数中 , 可以传入一个filter过滤器SimplePropertyPreFilter

SimplePropertyPreFilter 写在这个过滤器中的属性都会被解析

SimplePropertyPreFilter filter = new SimplePropertyPreFilter(
        "username","password" , "roleList" , "roleName" );//会解析写入的属性名称
//解析user对象的时候 , user对象中包含List<Role> 集合 , 解析role对象的时候 , role对象中有List<User> 集合 , 会陷入死循环状态
System.out.println(JSON.toJSONString(userA ,filter , SerializerFeature.DisableCircularReferenceDetect));//[{"password":"123456","username":"东方月初"},{"$ref":"$[0]"}]

被过滤的字段就会不显示 , 如果非要全部显示的话 , 介意修改属性名 , 让属性名布绒服

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
com.alibaba.fastjson.JSONException 是一个 JSON 解析/生成异常类,通常是由 fastjson 库在处理 JSON 字符串时发生错误导致的。 出现 "com.alibaba.fastjson.JSONException: write JavaBean error" 错误一般是由以下原因引起的: 1. JavaBean 对象和 JSON 字符串之间的属性不匹配。例如,JavaBean 对象缺少某些属性或 JSON 字符串包含了多余的属性,导致无法正确地将 JSON 字符串转换成 JavaBean 对象,或者无法将 JavaBean 对象转换成相应的 JSON 字符串。 解决方法:检查 JavaBean 对象和 JSON 字符串之间的属性是否一一对应并正确设置。 2. JavaBean 对象的属性和 JSON 字符串的属性类型不匹配。例如,JavaBean 对象中的属性是长整型,但是 JSON 字符串中对应的属性是字符串类型,导致类型转换错误。 解决方法:确保 JavaBean 对象的属性类型和 JSON 字符串中对应的属性类型一致。 3. JavaBean 对象中存在循环引用。即 JavaBean 对象的属性中包含了对自身的引用,导致 fastjson 无法正确处理。 解决方法:避免在 JavaBean 对象出现循环引用,可以通过在 JavaBean 对象中使用 @JSONField(serialize=false) 注解来标记该属性不被序列化。 总之,"com.alibaba.fastjson.JSONException: write JavaBean error" 错误通常是由于 fastjson 在处理 JSON 字符串和 JavaBean 对象之间的转换时出现问题。要解决这个错误,需要检查 JavaBean 对象和 JSON 字符串之间的属性是否匹配,并且确保属性类型一致。另外,要避免在 JavaBean 对象出现循环引用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值