开发者社区> 问答> 正文

严重bug,fastjson 2 序列化后不是标准的json格式,导致某些时刻反序列化报错

严重bug,序列化后不是标准的json格式,导致某些时刻反序列化报错

对象的属性为set集合时,序列化带类型,输出的并非json格式,导致某些时候无法解析。

直接上内容:下面这个set类型序列化之后,方括号前面有Set字符,并非标准的json格式。

public static void main(String[] args) {
    TestA t = new TestA();
    System.out.println(JSON.toJSONString(t, JSONWriter.Feature.WriteClassName, JSONWriter.Feature.PrettyFormat));
}

@Data
static class TestA {
    Set<String> colSet = new HashSet<>();
    List<String> colList = new ArrayList<>();
    Map<String, String> colMap = new HashMap<>();

    {
        colSet.add("a");
        colSet.add("b");
        colList.add("a");
        colList.add("b");
        colMap.put("a", "b");
    }
}

提问30.png

上面这个例子使用fastjson2进行反序列化是可以正常反序列化的,但是。。。。。。。。 如果使用此链接中的例子直接解析错误

再次附上源码:

@Test
void test() {
    String jsonStr = """
           {"@type":"top.jiangqiang.framework.system.entity.LoginUser","accountNonExpired":true,"accountNonLocked":true,"authorities":Set[{"@type":"org.springframework.security.core.authority.SimpleGrantedAuthority","authority":"123"},{"@type":"org.springframework.security.core.authority.SimpleGrantedAuthority","authority":"12312"}],"credentialsNonExpired":true,"enabled":true,"menuSet":Set[{"@type":"top.jiangqiang.framework.system.entity.vo.MenuVo","authority":"","component":"routerView/parent.vue","externalLink":false,"id":25,"menuSort":8,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isIframe":false,"isKeepAlive":true,"icon":"iconfont icon-diannao1","isAffix":false,"title":"测试名称","url":"","isHide":false},"name":"test","parentId":0,"path":"/test","redirect":""},{"@type":"top.jiangqiang.framework.system.entity.vo.MenuVo","component":"home/index.vue","externalLink":false,"id":1,"menuSort":1,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isLink":"","isIframe":false,"roles":["admin","common"],"isKeepAlive":true,"icon":"iconfont icon-shouye","isAffix":true,"title":"首页","isHide":false},"name":"home","parentId":0,"path":"/home"},{"@type":"top.jiangqiang.framework.system.entity.vo.MenuVo","authority":"","component":"3123123","externalLink":false,"id":51,"menuSort":0,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isIframe":false,"isKeepAlive":true,"icon":"","isAffix":false,"title":"123","url":"","isHide":false},"name":"3123","parentId":0,"path":"12312312","redirect":"1231"},{"@type":"top.jiangqiang.framework.system.entity.vo.MenuVo","authority":"123","component":"system/generator/index.vue","externalLink":false,"id":48,"menuSort":0,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isIframe":false,"isKeepAlive":true,"icon":"iconfont icon-diannao-shuju","isAffix":false,"title":"代码生成","url":"","isHide":false},"name":"112","parentId":0,"path":"/genCode","redirect":""},{"@type":"top.jiangqiang.framework.system.entity.vo.MenuVo","children":[{"component":"system/dept/index.vue","externalLink":false,"id":6,"menuSort":6,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isLink":"","isIframe":false,"roles":["admin"],"isKeepAlive":true,"icon":"ele-OfficeBuilding","isAffix":false,"title":"部门管理","isHide":false},"name":"systemDept","parentId":2,"path":"/system/dept"},{"component":"system/menu/index.vue","externalLink":false,"id":3,"menuSort":3,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isLink":"","isIframe":false,"roles":["admin"],"isKeepAlive":true,"icon":"iconfont icon-caidan","isAffix":false,"title":"菜单管理","isHide":false},"name":"systemMenu","parentId":2,"path":"/system/menu"},{"component":"system/user/index.vue","externalLink":false,"id":5,"menuSort":5,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isLink":"","isIframe":false,"roles":["admin"],"isKeepAlive":true,"icon":"iconfont icon-icon-","isAffix":false,"title":"用户管理","isHide":false},"name":"systemUser","parentId":2,"path":"/system/user"},{"component":"system/role/index.vue","externalLink":false,"id":4,"menuSort":4,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isLink":"","isIframe":false,"roles":["admin"],"isKeepAlive":true,"icon":"ele-ColdDrink","isAffix":false,"title":"角色管理","isHide":false},"name":"systemRole","parentId":2,"path":"/system/role"},{"authority":"","component":"system/i18n/index.vue","externalLink":false,"id":45,"menuSort":9,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isIframe":false,"isKeepAlive":true,"icon":"iconfont icon-diannao1","isAffix":false,"title":"国际化","url":"","isHide":false},"name":"i18n","parentId":2,"path":"/system/i18n","redirect":""},{"component":"system/dic/index.vue","externalLink":false,"id":7,"menuSort":7,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isLink":"","isIframe":false,"roles":["admin"],"isKeepAlive":true,"icon":"ele-SetUp","isAffix":false,"title":"字典管理","isHide":false},"name":"systemDic","parentId":2,"path":"/system/dic"}],"component":"routerView/parent.vue","externalLink":false,"id":2,"menuSort":2,"menuType":"menu","meta":{"@type":"java.util.LinkedHashMap","isLink":"","isIframe":false,"roles":["admin"],"isKeepAlive":true,"icon":"iconfont icon-xitongshezhi","isAffix":false,"title":"系统设置","isHide":false},"name":"system","parentId":0,"path":"/system","redirect":"/system/setting"}],"user":{"active":true,"deleted":false,"id":1,"nickname":"admin","password":"d29d20329fbd47d8b42fb2ac69069a4a104f215e509b85868c1f47ba9eab114dd6fdfe4d6812e7b7f498056f7b0ac5740c6c056e198632992fa8b9dd958e9bd5ef765b4e46b8fe58079eb6b10a7e563c4bee074b412138ca2d426a9b3f406ad3","username":"admin"}}
            """;
      Filter filter = JSONReader.autoTypeFilter(
            // 这里可以配置多个前缀
            "org.springframework.security.core.authority.SimpleGrantedAuthority",
            "org.springframework.util.LinkedCaseInsensitiveMap"
    );
    JSON.mixIn(SimpleGrantedAuthority.class, SimMixin.class);
    LoginUser loginUser = JSON.parseObject(jsonStr, LoginUser.class, filter);

    Object o = redisTemplate.opsForValue().get("sys:user:info:1");
    System.out.println(o);

}
static class SimMixin {
    @JSONCreator
    public SimMixin(@JSONField(value = true) String role) {
    }

    @JSONField(value = true)
    public String getAuthority() {
        return null;
    }
}

LoginUser

@Data @NoArgsConstructor public class LoginUser implements UserDetails { private User user; /** * 帐户是否过期 / private boolean accountNonExpired = true; /* * 帐户是否被锁定 / private boolean accountNonLocked = true; /* * 密码是否过期 / private boolean credentialsNonExpired = true; /* * 帐户是否可用 / private boolean enabled = true; /* * 拥有权限集合 */ private Set<? extends GrantedAuthority> authorities;

/**
 * 可访问的菜单集合
 */
private Set<MenuVo> menuSet;

public LoginUser(User user) {
    this.user = user;
}

@JSONField(serialize = false,deserialize = false)
public String getPassword() {
    return user.getPassword();
}

@JSONField(serialize = false,deserialize = false)
public String getUsername() {
    return user.getUsername();
}

} @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("sys_user") public class User extends BaseEntity {

@Serial
private static final long serialVersionUID = 1L;

/**
 * 用户名
 */
private String username;

/**
 * 昵称
 */
private String nickname;

/**
 * 姓名
 */
private String realName;

/**
 * 密码
 */
private String password;

/**
 * 头像
 */
private String avatar;

/**
 * 性别   0:男   1:女   2:未知
 */
private Byte gender;
/**
 * 启用/禁用
 */
private Boolean active;
/**
 * 邮箱
 */
private String email;

/**
 * 手机号
 */
private String mobile;
/**
 * 用户简介
 */
private String resume;

}

@Data public class BaseEntity implements Serializable { @Serial @TableField(exist = false) private static final long serialVersionUID = 1L;

@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
 * 创建时间
 */
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
 * 最后更新时间
 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/**
 * 是否删除
 */
@TableLogic
private Boolean deleted;

}

下面是错误日志

提问31.png

我一开始还以为是我复制的json字符串有问题,然后我使用了redisTemplate直接获取,报错一样的。然后我特意使用了别的json解析工具,报错也是同一个地方。定位到解析错误的字符,就是set类型标识。

原提问者GitHub用户jiangqiang1996

展开
收起
后端老大 2023-04-21 11:16:44 650 0
1 条回答
写回答
取消 提交回答
  • 使用WriteClassName之后,是要使用非标准的表示才能满足需求。

    两个选择:

    不使用WriteClassName 其他的场景也使用fastjson2 这个不是BUG,设计就是这样的

    https://github.com/alibaba/fastjson2/releases/tag/2.0.14 问题已修复,请用新版本

    原回答者GitHub用户wenshao

    2023-04-21 14:11:48
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载