[alibaba/fastjson]实体类只有一个get方法时报错

2023-12-15 53 views
8

我有一个User实体类,有一个RoleList属性和对应的get和set方法,还有一个getRoleIdList的方法,抽取RoleList中每个Role的id组成List返回,然后 JSONObject.parseObject(userString, User.class);反序列化时报错 java.lang.NoSuchMethodException: com.xQuant.platform.app.auth.entity.User.setRoleIdList(java.util.List) 经排查是76版本的FieldDeserializer中新增了degradeValueAssignment方法,但该方法中没有判断field为空的情况下试图获取setRoleIdList方法对象导致报错,导致实体类中的get方法如果没有对应属性就会报错

回答

6

请问有User以及getRoleldList的实现吗?

9

User就是普通的实体类,有一些基本属性,类似userId,userName,password,stats,roleList这些,这些都有get和set方法,就多了一个getRoleIdList方法

public List getRoleIdList() { if (roleList == null) { return null; } return Lists.transform(roleList, new Function<Role, Long>() { @Nullable @Override public Long apply(@Nullable Role input) { return input.getRoleId(); } }); }

0

你好!试着复现了一下这个情况,确实是缺少set方法时会报错,并且field为空。

package com.alibaba.json.bvt.issue_3700;

import com.alibaba.fastjson.JSON;
import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class Issue3732 extends TestCase {
    static class Role{
        int id;

        public Role() {}

        public Role(int id) {
            this.id = id;
        }

        public void setId(int id) {this.id = id;}

        public int getId() {
            return id;
        }
    }
    static class User{
        List<Role> roleList;

        public void setRoleList(List<Role> roleList) {
            this.roleList = roleList;
        }

        public List<Role> getRoleList() {
            return roleList;
        }

//        public void setRoleIdList(List<Integer> roleIdList){}

        public List<Integer> getRoleIdList(){ //去掉public则不报错
            if (roleList == null) return null;
            List<Integer> roleIdList = new ArrayList<Integer>();
            for (Role role : roleList) {
                roleIdList.add(role.id);
            }
            return roleIdList;
        }
    }

    @Test
    public void test_for_issue(){
        Role role1 = new Role(1);
        Role role2 = new Role(2);
        Role role3 = new Role(3);
        List<Role> roleList = new ArrayList<Role>();
        roleList.add(role1);
        roleList.add(role2);
        roleList.add(role3);
        User user = new User();
        user.roleList = roleList;
//        List <Integer> roleIdList = user.getRoleIdList();

        String userString = JSON.toJSONString(user);
        System.out.println(userString);

        User parseUser = JSON.parseObject(userString,User.class);
    }
}
3
public class TestCase {
    static class Role{
        int id;

        public Role() {}

        public Role(int id) {
            this.id = id;
        }

        public void setId(int id) {this.id = id;}

        public int getId() {
            return id;
        }
    }
    static class User{
        public List<Role> roleList;

        public void setRoleList(List<Role> roleList) {
            this.roleList = roleList;
        }

        public List<Role> getRoleList() {
            return roleList;
        }

//        public void setRoleIdList(List<Integer> roleIdList){}

        public List<Integer> getRoleIdList(){ 
            if (roleList == null) return null;
            List<Integer> roleIdList = new ArrayList<Integer>();
            for (Role role : roleList) {
                roleIdList.add(role.id);
            }
            return roleIdList;
        }
    }

    @Test
    public void test_for_issue(){
        Role role1 = new Role(1);
        Role role2 = new Role(2);
        Role role3 = new Role(3);
        List<Role> roleList = new ArrayList<Role>();
        roleList.add(role1);
        roleList.add(role2);
        roleList.add(role3);
        User user = new User();
        user.roleList = roleList;
//        List <Integer> roleIdList = user.getRoleIdList();

        String userString = JSON.toJSONString(user, new SerializeConfig(IdentityHashMap.DEFAULT_SIZE, true), new SerializeFilter[0]);
        System.out.println(userString);

        User parseUser = JSON.parseObject(userString,User.class);
        System.out.println(parseUser.toString());
    }
}

image

fieldBased

  • true: fastjson只会通过 clazz.getDeclaredFields() 获取 field, 此时只能获取到 roleList
  • false: fastjson会通过所有的方法去分析field,其中有一个判断是获取所有以 get 开头的方法,此时 getRoleList()getRoleIdList() 都会被用于解析propertyName进而获取到 roleList 和 roleIdList 两个 field, 而 roleIdList 并不是字段且没有set方法,所以反序列化的时候会报错
5

1.2.76同样发现此问题,目前发现1.2.78版本已经悄悄修复了,处理方法是直接catch起来了