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

Dart泛型场景下fromJson调用报错,如何实现通用的fromJson/toJson?

问题分析

Dart 中泛型类型参数 T 本质是 Type 对象,无法直接调用类的静态方法或工厂构造方法。尽管你的子类都重写了 fromJson 工厂构造,但泛型约束 T extends TestClass 仅保证 T 是 TestClass 的子类,而工厂构造属于类级成员,不属于实例继承范畴,因此编译器无法推断所有 T 类型都具备 fromJson 方法,从而报错。

解决方案

方案1:给方法传入 fromJson 回调函数

修改 FactoryController 的 listNetworkObjects 方法,新增一个接收 Map 并返回 T 的回调参数,直接传入对应子类的 fromJson 工厂构造:

class FactoryController{
  Future<List<T>> listNetworkObjects<T extends TestClass>({
    required List<String> filters,
    required T Function(Map<String, dynamic>) fromJson, // 新增回调参数
  }) async {
    try {
      final data = await MockApi().mockApiCall(filters);
      // 将API返回的列表数据逐个转换为T实例
      final List<T> allItems = (data as List).map((json) {
        return fromJson(json as Map<String, dynamic>);
      }).toList();

      if (allItems.isNotEmpty) {
        print('Received Items from the API.');
      }
      return allItems;
    } catch (getTestClassError, stackTrace) {
      print('Error getting TestClasses');
      print(stackTrace);
      return <T>[];
    }
  }
}

调用示例:

final controller = FactoryController();
// 获取ATest列表
controller.listNetworkObjects<ATest>(
  filters: ['filter1'],
  fromJson: ATest.fromJson,
);
// 获取BTest列表
controller.listNetworkObjects<BTest>(
  filters: ['filter2'],
  fromJson: BTest.fromJson,
);

方案2:将 fromJson 回调注入到控制器实例

如果不想每次调用方法都传回调,可以在 FactoryController 初始化时传入 fromJson,绑定到特定子类:

class FactoryController<T extends TestClass>{
  final T Function(Map<String, dynamic>) _fromJson;

  // 构造器注入回调
  FactoryController(this._fromJson);

  Future<List<T>> listNetworkObjects({
    required List<String> filters,
  }) async {
    try {
      final data = await MockApi().mockApiCall(filters);
      final List<T> allItems = (data as List).map((json) {
        return _fromJson(json as Map<String, dynamic>);
      }).toList();

      if (allItems.isNotEmpty) {
        print('Received Items from the API.');
      }
      return allItems;
    } catch (getTestClassError, stackTrace) {
      print('Error getting TestClasses');
      print(stackTrace);
      return <T>[];
    }
  }
}

调用示例:

// 创建绑定ATest的控制器
final aController = FactoryController<ATest>(ATest.fromJson);
aController.listNetworkObjects(filters: ['filter1']);

// 创建绑定BTest的控制器
final bController = FactoryController<BTest>(BTest.fromJson);
bController.listNetworkObjects(filters: ['filter2']);

补充:修正MockApi返回格式

原 MockApi 返回单个 Map,不符合列表数据场景,建议修改为返回列表:

class MockApi{
  MockApi();

  Future<List<Map<String, dynamic>>> mockApiCall(List<String> filters) async {
    // 模拟API返回多个数据项
    return [{"test": "object1"}, {"test": "object2"}];
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 07:15:39