使用Fastjson反序列化时因无默认构造函数失败的解决咨询
解决Fastjson反序列化时“无默认构造函数”的问题
问题根源
你碰到的default constructor not found错误,本质是Fastjson默认依赖类的无参构造函数来创建实例,再通过setter方法完成属性赋值。但你的Student类只定义了带参构造——Java规则是:当类显式声明了任何构造函数时,编译器就不会自动生成默认的无参构造,所以Fastjson找不到可用的实例化入口,导致反序列化失败。
结合你说的实际场景:大量类来自外部Maven依赖,几乎无法修改源码,下面给你几种适配不同场景的解决方案:
方案1:给可修改的类添加无参构造(示例场景适用)
如果是你自己维护的类(比如示例里的Student),最简单的办法就是加一个空的无参构造:
public class Student { private String name; private String age; // 新增无参构造 public Student() {} Student(String name,String age){ this.name = name; this.age = age; } // 原有的getter、setter和toString方法不变 }
添加后Fastjson就能正常实例化并完成反序列化了。
方案2:用Fastjson注解指定构造函数(可修改类适用)
如果不想加无参构造,可以用@JSONCreator标记带参构造,配合@JSONField绑定JSON字段与构造参数的映射关系:
public class Student { private String name; private String age; @JSONCreator public Student(@JSONField(name = "name") String name, @JSONField(name = "age") String age) { this.name = name; this.age = age; } // 原有的getter、setter和toString方法不变 }
这样Fastjson会直接调用这个带参构造创建实例,不需要依赖无参构造。
方案3:自定义反序列化器(不可修改的第三方类适用)
对于无法修改源码的依赖类,自定义反序列化器是最通用的解法。通过反射或者手动赋值的方式,绕过无参构造的限制:
import com.alibaba.fastjson.parser.DefaultJSONParser; import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONException; import java.lang.reflect.Constructor; import java.lang.reflect.Type; public class StudentDeserializer implements ObjectDeserializer { @Override public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { // 先把JSON解析成JSONObject JSONObject jsonObj = parser.parseObject(); // 提取字段值 String name = jsonObj.getString("name"); String age = jsonObj.getString("age"); // 通过反射调用带参构造创建实例 try { Constructor<Student> constructor = Student.class.getConstructor(String.class, String.class); return (T) constructor.newInstance(name, age); } catch (Exception e) { throw new JSONException("反序列化Student失败", e); } } @Override public int getFastMatchToken() { return JSONToken.LBRACE; } }
然后在反序列化前注册这个反序列化器:
// 全局注册反序列化器 ParserConfig.getGlobalInstance().putDeserializer(Student.class, new StudentDeserializer()); // 正常执行反序列化 Student model2 = JSON.parseObject(hell, Student.class);
方案4:开启非公共构造支持特性(类存在私有无参构造时适用)
如果第三方类有private的无参构造,可以开启Fastjson的Feature.SupportNonPublicConstructor特性,让Fastjson能够访问私有构造:
Student model2 = JSON.parseObject(hell, Student.class, Feature.SupportNonPublicConstructor);
总结
结合你的实际场景(大量依赖类无法修改),方案3的自定义反序列化器是最适合的选择,你可以封装通用的反射实例化逻辑,减少重复代码。
内容的提问来源于stack exchange,提问作者Vineel




