You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用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

火山引擎 最新活动