You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gson序列化/反序列化嵌套多态Rule类集合问题求助

问题描述

我有如下类结构:

public abstract class Rule { .... }
public class RuleType1 extends Rule { ... }
public class RuleType2 extends Rule { ... }
public class RuleType3 extends Rule { ... }
public class RuleType4 extends Rule { ... }

public class RuleSet extends Rule {
     ... 
     private final Collection<Rule> rules;
}

我需要解析包含多层嵌套Rule子类的JSON,由于RuleSet内部包含Rule集合,所以它也可以嵌套其他RuleSet。我不想实现自定义(反)序列化器,因为这会降低子类灵活性——修改子类时还得同步修改序列化器。

需要序列化/反序列化的JSON示例如下:

{
    "ruleType": "ruleSet",
    "rules": [
        {
            "ruleType": "ruleSet",
            "rules": [
                {
                    "ruleType": "RuleType1"
                },
                {
                    "ruleType": "ruleSet",
                    "rules": [
                        {
                            "ruleType": "RuleType2"
                        },
                        {
                            "ruleType": "RuleType3"
                        }
                    ]
                }
            ]
        },
        {
            "ruleType": "ruleSet",
            "rules": [
                {
                    "ruleType": "RuleType1"
                },
                {
                    "ruleType": "ruleSet",
                    "rules": [
                        {
                            "ruleType": "RuleType3"
                        },
                        {
                            "ruleType": "RuleType4"
                        }
                    ]
                }
            ]
        }
    ]
}

补充信息

实际项目中类结构有所调整:RuleSet包含Collection<IRule> rules,另外定义了SampleClass:

public class SampleClass {
    public IRule parameters;
    public double defaultConfidence;
    public String ruleType;
}

我用RuntimeTypeAdapterFactory配置Gson:

static RuntimeTypeAdapterFactory<IRule> adaptor = RuntimeTypeAdapterFactory.of(IRule.class)
        .registerSubtype(RuleSet.class)
        .registerSubtype(Rule.class);

static RuntimeTypeAdapterFactory<Rule> ruleAdaptor = RuntimeTypeAdapterFactory.of(Rule.class)
        .registerSubtype(DocumentTypesRule.class)
        .registerSubtype(DataAttributesRule.class)
        .registerSubtype(DictionariesRule.class)
        .registerSubtype(FileFormatsRule.class)
        .registerSubtype(FileLengthRule.class)
        .registerSubtype(FileNamePatternsRule.class)
        .registerSubtype(FixedRule.class)
        .registerSubtype(ImageTypesRule.class)
        .registerSubtype(KeywordsRule.class)
        .registerSubtype(RegexesRule.class)
        .registerSubtype(SimilaritiesRule.class)
        .registerSubtype(TopicsRule.class);

private static final Gson GSON = new GsonBuilder()
        .registerTypeAdapterFactory(adaptor)
        .registerTypeAdapterFactory(ruleAdaptor)
        .create();

调用GSON.fromJson(response, SampleClass.class)时抛出错误:

java.lang.RuntimeException: Unable to invoke no-args constructor for interface <classPath>.IRule. Registering an InstanceCreator with Gson for this type may fix this problem.

解决方案

问题根源

错误核心在于:Gson无法实例化接口IRule,且你的适配器配置层级断裂——你把抽象类Rule注册为IRule的子类型,但Rule本身无法实例化;同时所有具体Rule子类只注册到了Rule的适配器,没有纳入IRule的多态处理链,导致Gson解析IRule类型时找不到具体实现类的构造逻辑。

修正步骤

  1. 合并适配器配置,统一注册到IRule
    不需要为Rule单独创建适配器,直接将所有具体Rule子类和RuleSet都注册到IRule的RuntimeTypeAdapterFactory中(需确保Rule实现IRule,RuleSet继承Rule),同时指定JSON中标识类型的字段名"ruleType":

    static RuntimeTypeAdapterFactory<IRule> ruleAdapter = RuntimeTypeAdapterFactory.of(IRule.class, "ruleType")
            // 注册RuleSet,对应JSON中的ruleType值
            .registerSubtype(RuleSet.class, "ruleSet")
            // 注册所有具体Rule子类,注意和JSON中的ruleType值一一对应
            .registerSubtype(DocumentTypesRule.class, "DocumentTypesRule")
            .registerSubtype(DataAttributesRule.class, "DataAttributesRule")
            .registerSubtype(DictionariesRule.class, "DictionariesRule")
            .registerSubtype(FileFormatsRule.class, "FileFormatsRule")
            .registerSubtype(FileLengthRule.class, "FileLengthRule")
            .registerSubtype(FileNamePatternsRule.class, "FileNamePatternsRule")
            .registerSubtype(FixedRule.class, "FixedRule")
            .registerSubtype(ImageTypesRule.class, "ImageTypesRule")
            .registerSubtype(KeywordsRule.class, "KeywordsRule")
            .registerSubtype(RegexesRule.class, "RegexesRule")
            .registerSubtype(SimilaritiesRule.class, "SimilaritiesRule")
            .registerSubtype(TopicsRule.class, "TopicsRule");
    
    private static final Gson GSON = new GsonBuilder()
            .registerTypeAdapterFactory(ruleAdapter)
            .create();
    
  2. 确保所有子类存在无参构造器
    Gson默认要求类具有无参构造器(显式定义或隐式生成均可),如果你的Rule子类或RuleSet只有带参构造器,需显式添加无参构造器,或使用Lombok的@NoArgsConstructor注解自动生成。

  3. 优化SampleClass字段(可选)
    SampleClass中同时存在IRule parameters和String ruleType,如果JSON中的ruleType仅用于标识parameters的类型,可删除SampleClass中的ruleType字段——RuntimeTypeAdapterFactory会自动通过JSON中的ruleType字段确定parameters的具体实现类。若业务需要保留该字段,确保其值与JSON中的对应即可。

验证

调整配置后重新调用GSON.fromJson(response, SampleClass.class),即可正常完成嵌套结构的反序列化。


内容的提问来源于stack exchange,提问作者Sahib Yar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 08:35:24