Dart:具有.fromJson构造函数的通用泛型

12
在Swift中,我习惯设置一个“protocol JSONInitializable”,它定义了一个“init?(json: JSON)”意味着符合该协议的所有类和结构都可以使用JSON对象进行初始化。
这是否意味着在Dart中(使用“abstract class”)不可能实现此功能,因为静态方法和工厂初始化程序不会从抽象类继承?
我问这个问题是因为我正在编写许多类似的API GET请求方法,这些方法可以很容易地合并成一个,例如:
static Future<T> get<T extends JSONInitializable>(int id) async {
  final resourceName = T; // TODO: transform to snake case
  final uri = Uri.parse("$kApiHostname/api/$resourceName/$id");

  final response = await _secureGet(uri);
  if (response == null) {
    return null;
  }

  final responseJson = json.decode(response.body);
  final model = T.fromJson(responseJson);

  return model;
}

但是为了让它正常工作,我需要将T限制为一个定义了.fromJson()初始化程序的协议/接口。


2
不,这对于静态方法和工厂初始化器来说是不可能的。 - Günter Zöchbauer
@GünterZöchbauer 这种情况有什么替代方案吗?我也在寻找同样的解决方法。 - Johnykutty
我也想知道这是否可能。 - Nova Entropy
我也在想如何以通用的方式实现它。 - Zheng Xing
也在寻找这个,因为它可以减少很多冗余代码。 - Simon
3个回答

1

0
手动解决方法可能是拥有一个序列化器、反序列化器的映射表,例如:
//Register object 1 in singleton
  JsonMapper.register<MyObject>(JsonObjectMapper(
    (mapper, map) => MyObject.fromJson(map),
    (mapper, instance) => instance.toJson(),
  ));
//Register object 2 in singleton...
...

通过这种方式,只要您已经注册了对象,就可以对其进行反序列化和序列化,而无需使用其通用类型。

自动(技术上生成的)方法是使用类似simple_json的包来帮助您绕过这个问题,使用一些代码生成,以便您不会搞乱注册和消除映射器。

而且,真正将您的对象从JSON转换为对象并从对象转换为JSON的代码实际上并没有存储在对象本身中,而是存储在生成的类中,因此将序列化和反序列化的责任从对象推到了生成的代码中(以分离的方式)。

请谨慎考虑我的建议,因为使用这两种方法都会失去静态类型检查,无法确定类型是否已注册映射器并可以转换。


0

这个答案可能会有帮助。你可以简单地将你的fromJson构造函数作为参数传递。

我遵循的简单步骤

  1. 创建一个抽象类

    抽象类 BaseModel { factory BaseModel.fromJson(Map<String, dynamic> json) { throw UnimplementedError(); } Map<String, dynamic>? toJson(); }

  2. 实现基类

    @JsonSerializable() class ServerStatus implements BaseModel { ServerStatus(this.status, this.message); String status = ''; String message = '';

    @override factory ServerStatus.fromJson(Map<String, dynamic> json) => _$ServerStatusFromJson(json);

    @override Map<String, dynamic>? toJson() => _$ServerStatusToJson(this); }

  3. 在你的逻辑类中,你要访问你的 fromJson 方法

    class CustomHttp { CustomHttp(this. Constructor); T Function(Map<String, dynamic>) constructor; Future<Object?> get(String path) async { final response = await http.get(this.uri); final Map<String, dynamic> parsed = json.decode(response. Body); return constructor(parsed); } }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接