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

Dart泛型场景下调用Enum.values实现枚举JSON序列化问题

Dart 原生实现泛型枚举序列化的解决方案

问题原因

Dart 中枚举的 values 是对应枚举类的静态属性,静态成员不属于类的继承体系,编译期就需要确定引用指向,无法通过泛型类型参数T在运行时动态获取,所以直接调用T.values会触发编译错误。

可选原生解决方案

方案1:调用时传入枚举values列表(最推荐)

这是无任何额外依赖、全平台兼容(包括Flutter)、性能最优的方案,仅需要调整方法定义,增加values入参:

// 泛型约束为Enum类型,避免传入非枚举类型
T? getEnum<T extends Enum>(String key, List<T> values) {
  final int? storedIndex = _pref?.getInt(key);
  // 增加边界校验,避免存储非法索引导致崩溃
  if (storedIndex == null || storedIndex < 0 || storedIndex >= values.length) {
    return null;
  }
  return values[storedIndex];
}

调用方式如下:

GenderType? gender = getEnum('user_gender', GenderType.values);

方案2:维护全局枚举映射表

如果希望调用时不用每次传values,可以提前手动维护所有需要序列化的枚举映射,不需要反射,同样兼容Flutter:

// 提前注册所有需要用到的枚举values
final Map<Type, List<Enum>> _enumValuesRegistry = {
  GenderType: GenderType.values,
  // 新增枚举时在此处追加即可
};

T? getEnum<T extends Enum>(String key) {
  final List<T>? values = _enumValuesRegistry[T] as List<T>?;
  final int? storedIndex = _pref?.getInt(key);
  if (values == null || storedIndex == null || storedIndex < 0 || storedIndex >= values.length) {
    return null;
  }
  return values[storedIndex];
}

调用方式如下:

GenderType? gender = getEnum<GenderType>('user_gender');

方案3:反射实现(仅纯Dart项目可用)

如果是纯Dart服务端/脚本项目,不需要兼容Flutter,可以用dart:mirrors反射实现自动获取values,无需手动维护映射,但注意Flutter默认禁用反射会导致打包失败,不建议Flutter项目使用。

注意事项

  • 所有方案都增加了索引边界校验,避免本地存储的非法索引值导致数组越界崩溃
  • 如果需要序列化为字符串而非索引,可以直接用枚举的name属性,反序列化时用values.firstWhere((e) => e.name == storedStr, orElse: () => null)匹配即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:45:04