我有一个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方法如果没有对应属性就会报错
Q
[alibaba/fastjson]实体类只有一个get方法时报错
8
A
回答
6
请问有User以及getRoleldList的实现吗?
9
User就是普通的实体类,有一些基本属性,类似userId,userName,password,stats,roleList这些,这些都有get和set方法,就多了一个getRoleIdList方法
public List
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());
}
}
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起来了