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

Dart泛型类SharedPreferencesObserver解析JSON遇类型转换错误,如何调用fromJson?

解决Dart泛型类中调用fromJson解析JSON的问题

问题原因

直接执行json.decode(jsonString) as T会抛出类型转换异常,因为json.decode返回的是Map<String, dynamic>类型,而非AuthResponse实例。Dart泛型无法直接调用T.fromJson静态方法,因为泛型在运行时会擦除类型信息,静态方法属于类本身而非实例,无法通过泛型参数直接访问。

解决方案1:传递解析函数到泛型类构造函数

这是最直接灵活的方案,无需修改现有实体类结构,只需在创建泛型实例时传入对应的fromJson工厂方法。

修改后的SharedPreferencesObserver类

import 'dart:convert';
import 'package:flutter/foundation.dart';
// 假设你已定义SharedPreferencesManager

class SharedPreferencesObserver<T> extends ChangeNotifier {
  late String _keyParam;
  T? _value;

  SharedPreferencesObserver(
    String key,
    T Function(Map<String, dynamic>) fromJson, // 新增解析函数参数
  ) {
    _keyParam = key;
    final jsonString = SharedPreferencesManager.instance.getString(key);
    try {
      if (jsonString != null) {
        final jsonMap = json.decode(jsonString) as Map<String, dynamic>;
        _value = fromJson(jsonMap); // 使用传入的解析函数创建实例
      } else {
        _value = null;
      }
    } catch (e) {
      _value = null;
    }
  }

  // 获取当前值
  T? get value => _value;
}

使用示例

创建AuthResponse对应的观察者实例时,直接传入AuthResponse.fromJson:

final authObserver = SharedPreferencesObserver<AuthResponse>(
  'auth_token_key',
  AuthResponse.fromJson,
);

解决方案2:通过抽象类约束+解析函数

如果希望通过抽象类统一约束所有可序列化的实体类,可以定义一个抽象类,让实体类实现它,再结合解析函数使用。

定义抽象类

abstract class JsonSerializable<T> {
  factory JsonSerializable.fromJson(Map<String, dynamic> json) = T;
}

修改AuthResponse实现抽象类

class AuthResponse extends JsonSerializable<AuthResponse> {
  final String token;

  AuthResponse({required this.token});

  Map<String, dynamic> toJson() {
    return {
      'token': token,
    };
  }

  @override
  factory AuthResponse.fromJson(Map<String, dynamic> json) {
    return AuthResponse(
      token: json['token'],
    );
  }
}

泛型类添加约束

修改泛型类,限定T必须实现JsonSerializable<T>,同时仍需传入解析函数(因为静态方法无法通过泛型参数直接调用):

class SharedPreferencesObserver<T extends JsonSerializable<T>> extends ChangeNotifier {
  late String _keyParam;
  T? _value;

  SharedPreferencesObserver(
    String key,
    T Function(Map<String, dynamic>) fromJson,
  ) {
    _keyParam = key;
    final jsonString = SharedPreferencesManager.instance.getString(key);
    try {
      if (jsonString != null) {
        final jsonMap = json.decode(jsonString) as Map<String, dynamic>;
        _value = fromJson(jsonMap);
      } else {
        _value = null;
      }
    } catch (e) {
      _value = null;
    }
  }

  T? get value => _value;
}

使用示例

和方案1一致,传入AuthResponse.fromJson即可:

final authObserver = SharedPreferencesObserver<AuthResponse>(
  'auth_token_key',
  AuthResponse.fromJson,
);

总结

方案1无需修改实体类,灵活性更高,是更推荐的实现方式;方案2通过抽象类统一约束实体类,适合需要统一管理序列化逻辑的场景。两种方案核心都是通过传递解析函数,绕过泛型无法直接调用静态方法的限制,将JSON Map转换为目标实体类实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:57:10