在 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()
初始值设定项的协议/接口。
您想要的功能在 Dart 中不可用(或计划中),但已经有过讨论。
手动解决方法可能是拥有序列化器、反序列化器的映射,例如:
//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 的实际代码并不存储在对象本身中,而是存储在生成的类中,从而将序列化反序列化的责任从对象推到生成的代码中(以解耦的方式) ).
请对我的建议持保留态度,因为这两种方法都会丢失静态类型检查,检查类型是否具有已注册的映射器并且可以转换。
这个答案可能会有所帮助。您只需将 fromJson 构造函数作为参数传递即可。
我遵循的简单步骤
创建一个抽象类
抽象类BaseModel{
工厂 BaseModel.fromJson(Map
实现基类
@JsonSerialized() 类 ServerStatus 实现 BaseModel { ServerStatus(this.status, this.message); 字符串状态=''; 字符串消息 = '';
@覆盖
工厂 ServerStatus.fromJson(Map
@覆盖
地图
在您尝试访问 fromJson 方法的逻辑类中
类 CustomHttp {
CustomHttp(this.构造函数);
T Function(Map
不幸的是,Dart 不支持实现此目标的一些非常重要的功能:从泛型参数调用静态方法。例如。在 C++ 模板(虽然不是泛型)中,您可以编写如下代码:
template<typename T>
T deserialize(MyStream istrm) { return T.deserialize(istrm); }
但是正如之前的答案中提到的,我们不能在 dart 中做同样的事情。
目前在我的解决方案中我使用反射。
尽管 dart 有内置的 mirrors,但是(突然)flutter 不支持它。因此我们被要求在 flutter 中使用 reflectable 包。你能感觉到吗?当我们试图解决一个问题时,却遇到了另一个问题。尽管如此。
使用反射,您可以扫描模块中具有特定注释(例如
@my_deserializable
)的类,然后收集静态方法。请注意,您可以编写自己的注释。
因此你可以建立一个工厂缓存,就像
Map<Type, Function(MyStream istrm)> deserializers
一样。因此,拥有这样的工厂,您就可以按如下方式使用它:
deserializers[T]!(responseJson);