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

使用Moshi PolymorphicJsonAdapterFactory反序列化嵌套集合遇问题

问题

复杂嵌套数据类型无法通过标准方法反序列化为目标类。现有一段可正常运行的代码,能将JSON反序列化为Map<String, ? extends T>结构:

private static <T> Map<String, ? extends T> deserializeTypeAdaptableJson(Class<T> baseType, List<Class<? extends T>> subclasses, String json) {
    PolymorphicJsonAdapterFactory<T> factory = PolymorphicJsonAdapterFactory.of(baseType, "type");
    for (Class<? extends T> subclass : subclasses) {
        factory = factory.withSubtype(subclass, subclass.getSimpleName());
    }
    Moshi moshi = new Moshi.Builder().add(factory).build();
    ParameterizedType type = Types.newParameterizedType(Map.class, String.class, baseType);
    JsonAdapter<Map<String, ? extends T>> adapter = moshi.adapter(type);
    return adapter.fromJson(json);
}

实际需要反序列化的是Map<String, List<? extends T>>,修改后的代码如下:

private static <T> Map<String, List<? extends T>> deserializeTypeAdaptableJson(Class<T> baseType, List<Class<? extends T>> subclasses, String json) {
    PolymorphicJsonAdapterFactory<T> factory = PolymorphicJsonAdapterFactory.of(baseType, "type");
    for (Class<? extends T> subclass : subclasses) {
        factory = factory.withSubtype(subclass, subclass.getSimpleName());
    }
    Moshi moshi = new Moshi.Builder().add(factory).build();
    ParameterizedType type = Types.newParameterizedType(Map.class, String.class, List.class, baseType);
    JsonAdapter<Map<String, List<? extends T>>> adapter = moshi.adapter(type);
    return adapter.fromJson(json);
}

虽然能得到正确的Map结构(键为String,值为List),但列表内的元素并非子类实例,而是带有"type"属性的Gson LinkedHashTreeMap。未找到嵌套集合反序列化的示例,请问需要添加什么配置?

解决方法

问题出在Types.newParameterizedType的使用逻辑上,需要先创建嵌套的List参数化类型,再将其作为Map的值类型传入,而非直接把List.class和baseType并列传入。

修改后的完整代码

private static <T> Map<String, List<? extends T>> deserializeTypeAdaptableJson(Class<T> baseType, List<Class<? extends T>> subclasses, String json) {
    PolymorphicJsonAdapterFactory<T> factory = PolymorphicJsonAdapterFactory.of(baseType, "type");
    for (Class<? extends T> subclass : subclasses) {
        factory = factory.withSubtype(subclass, subclass.getSimpleName());
    }
    Moshi moshi = new Moshi.Builder().add(factory).build();
    
    // 先构建List<? extends T>对应的参数化类型
    ParameterizedType listType = Types.newParameterizedType(List.class, baseType);
    // 再构建Map<String, List<? extends T>>的参数化类型
    ParameterizedType mapType = Types.newParameterizedType(Map.class, String.class, listType);
    
    JsonAdapter<Map<String, List<? extends T>>> adapter = moshi.adapter(mapType);
    return adapter.fromJson(json);
}

原理说明

原代码中Types.newParameterizedType(Map.class, String.class, List.class, baseType)的写法不符合方法规则:该方法第一个参数是主类型,后续参数是主类型的泛型参数。Map的泛型参数仅为2个(Key和Value),传入3个参数会导致Moshi无法识别List内部的泛型类型,无法应用多态适配器,最终只能将列表元素反序列化为默认的LinkedHashTreeMap。

通过先构建List的参数化类型,再将其作为Map的Value类型传入,Moshi就能正确识别List内部需要反序列化的泛型类型,从而应用配置的PolymorphicJsonAdapterFactory,将列表元素正确反序列化为对应的子类实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:10:31