【发布时间】:2020-12-02 14:09:54
【问题描述】:
我有一个来自 API 的 JSON 数据结构,其中包含一些字段。
我想创建一个 Freezed 模型,它有一个工厂来创建正确的子类,具体取决于其中一个字段的类型。
这是我的代码:
abstract class ItineraryData<T> implements _$ItineraryData<T> {
const ItineraryData._();
const factory ItineraryData({
List<dynamic> summary,
double totalPrice,
double totalSeparatePay,
double totalTax,
List<String> covidAlerts,
}) = _ItineraryData;
const factory ItineraryData.flight({
List<FlightSummary> summary,
double totalPrice,
double totalSeparatePay,
double totalTax,
List<String> covidAlerts,
}) = _FlightItineraryData;
const factory ItineraryData.hotel({
List<HotelSummary> summary,
double totalPrice,
double totalSeparatePay,
double totalTax,
}) = _HotelItineraryData;
const factory ItineraryData.car({
List<CarSummary> summary,
double totalPrice,
double totalSeparatePay,
double totalTax,
List<String> covidAlerts,
}) = _CarItineraryData;
factory ItineraryData.fromJson(Map json) => _$ItineraryDataFromJson(json);
}
在这种情况下,访问ItineraryData<A> 的引用永远不会有summary 列表字段(应该始终存在,但类型不同)。
然后我尝试将未命名的构造函数更改为在 List 类型中使用<T>:
const factory ItineraryData({
List<T> summary,
double totalPrice,
double totalSeparatePay,
double totalTax,
List<String> covidAlerts,
}) = _ItineraryData;
然后我收到以下错误:
Could not generate `fromJson` code for `summary` because of type `T` (type parameter).
None of the provided `TypeHelper` instances support the defined type.
To support type paramaters (generic types) you can:
1) Use `JsonConverter`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonConverter-class.html
2) Use `JsonKey` fields `fromJson` and `toJson`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html
3) Set `JsonSerializable.genericArgumentFactories` to `true`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/genericArgumentFactories.html
package:<???>/models/itinerary_data.freezed.dart:253:17
╷
253 │ final List<T> summary;
│ ^^^^^^^
╵
[INFO] Running build completed, took 221ms
我确实尝试过添加转换器,如下所示:
class ItineraryDataConverter
implements JsonConverter<ItineraryData, Map<String, dynamic>> {
const ItineraryDataConverter();
@override
ItineraryData fromJson(Map<String, dynamic> json) {
if (json == null || !json.containsKey('data')) {
return null;
}
json = json['data'];
// type data was already set (e.g. because we serialized it ourselves)
if (!json.keys
.any((k) => ['cabin_class', 'hotel', 'car_type'].contains(k))) {
return ItineraryData.fromJson(json);
}
// you need to find some condition to know which type it is. e.g. check the presence of some field in the json
if (json.containsKey('cabin_class')) {
return _FlightItineraryData.fromJson(json);
} else if (json.containsKey('hotel')) {
return _HotelItineraryData.fromJson(json);
} else if (json.containsKey('car_type')) {
return _CarItineraryData.fromJson(json);
} else {
throw Exception(
'Could not determine the constructor for mapping from JSON');
}
}
@override
Map<String, dynamic> toJson(ItineraryData data) => data.toJson();
}
但我仍然遇到同样的错误。
我如何确保summary 是可见的 + 子类的强类型?
或者更好的方法是什么?
【问题讨论】: