json - 如何在 Dart 中使用带有 json 序列化的泛型和泛型列表?
问题描述
我正在开发一个使用 Flutter 制作的移动项目。该项目需要连接到一些服务器以进行 REST 消费服务(GET、POST、PUT、DELETE,...),并检索数据以及向它们发送数据。数据需要以 JSON 格式格式化,因此我决定将 Json 序列化库 2.0.3 用于 Dart,并带有 Json 注释 2.0.0 和 build_runner 1.2.8;它确实适用于 int、String 和 bool 等基本数据类型以及自定义对象。但它似乎根本不适用于泛型,例如<T> item;
字段或List<T> list;
字段。
我的目的是添加一些通用字段,以便它们可用于返回所有类型的 json 类型和结构。我设法为第一种情况找到了解决方案,通过使用“@JsonKey”覆盖 fromJson 和 toJson,并<T>
与我想在方法中将其转换为的所需类型进行比较。但是,我找不到List<T>
键入字段的解决方案。如果我尝试为它们使用注释,我得到的只是一个List<dynamic>
类型,它对于比较类进行强制转换是无用的。我该如何解决我的困境?我应该坚持使用 json_serialization 还是改用 build_value ?非常感谢您对此事的任何帮助。
我的代码:
import 'package:json_annotation/json_annotation.dart';
part 'json_generic.g.dart';
@JsonSerializable()
class JsonGeneric<T> {
final int id;
final String uri;
final bool active;
@JsonKey(fromJson: _fromGenericJson, toJson: _toGenericJson)
final T item;
@JsonKey(fromJson: _fromGenericJsonList, toJson: _toGenericJsonList)
final List<T> list;
static const String _exceptionMessage = "Incompatible type used in JsonEnvelop";
JsonGeneric({this.id, this.uri, this.active, this.item, this.list});
factory JsonGeneric.fromJson(Map<String, dynamic> json) =>
_$JsonGenericFromJson(json);
Map<String, dynamic> toJson() => _$JsonGenericToJson(this);
static T _fromGenericJson<T>(Map<String, dynamic> json) {
if (T == User) {
return json == null ? null : User.fromJson(json) as T;
} else if (T == Company) {
return json == null ? null : Company.fromJson(json) as T;
} else if (T == Data) {
return json == null ? null : Data.fromJson(json) as T;
} else {
throw Exception(_exceptionMessage);
}
}
static Map<String, dynamic> _toGenericJson<T>(T value) {
if (T == User) {
return (T as User).toJson();
} else if(T == Company) {
return (T as Company).toJson();
} else if(T == Data) {
return (T as Data).toJson();
} else {
throw Exception(_exceptionMessage);
}
}
static dynamic _fromGenericJsonList<T>(List<dynamic> json) {
if (T == User) {
} else if(T == Company) {
} else if(T == Data) {
} else {
throw Exception(_exceptionMessage);
}
}
static List<Map<String, dynamic>> _toGenericJsonList<T>(dynamic value) {
if (T == User) {
} else if(T == Company) {
} else if(T == Data) {
} else {
throw Exception(_exceptionMessage);
}
}
}
我希望能够序列化/反序列化“最终列表”;使用“@JsonKey”或不使用它,但到目前为止,我未能找到将其转换为正确 json 格式的方法。
当我尝试为此类生成代码时(使用命令“flutter packages pub run build_runner build”),我最终收到以下错误:
运行 JsonSerializableGenerator 时出错由于类型无法生成fromJson
代码。提供的实例都不支持定义的类型。包:json_generic.dart:11:17list
T
TypeHelper
╷
11 │ final List<T> list;
│ ^^^^
╵
解决方案
这是我的正确解决方案,非常适合我。
class Paginate<T> {
int from;
int index;
int size;
int count;
int pages;
List<T> items;
bool hasPrevious;
bool hasNext;
Paginate(
{this.index,
this.size,
this.count,
this.from,
this.hasNext,
this.hasPrevious,
this.items,
this.pages});
factory Paginate.fromJson(Map<String,dynamic> json,Function fromJsonModel){
final items = json['items'].cast<Map<String, dynamic>>();
return Paginate<T>(
from: json['from'],
index: json['index'],
size: json['size'],
count: json['count'],
pages: json['pages'],
hasPrevious: json['hasPrevious'],
hasNext: json['hasNext'],
items: new List<T>.from(items.map((itemsJson) => fromJsonModel(itemsJson)))
);
}
}
假设我们将使用飞行模型分页模型。在这里您必须配置航班列表。
class Flight {
String flightScheduleId;
String flightId;
String flightNo;
String flightDate;
String flightTime;
Flight(
{this.flightScheduleId,
this.flightId,
this.flightNo,
this.flightDate,
this.flightTime});
factory Flight.fromJson(Map<String, dynamic> parsedJson) {
var dateFormatter = new DateFormat(Constants.COMMON_DATE_FORMAT);
var timeFormatter = new DateFormat(Constants.COMMON_TIME_FORMAT);
var parsedDate = DateTime.parse(parsedJson['flightDepartureTime']);
String formattedDate = dateFormatter.format(parsedDate);
String formattedTime = timeFormatter.format(parsedDate);
return Flight(
flightScheduleId: parsedJson['id'],
flightId: parsedJson['flightLayoutId'],
flightNo: parsedJson['outboundFlightName'],
flightDate: formattedDate,
flightTime: formattedTime,
}
// Magic goes here. you can use this function to from json method.
static Flight fromJsonModel(Map<String, dynamic> json) => Flight.fromJson(json);
}
-> 在这里你可以使用,
Paginate<Flight>.fromJson(responses, Flight.fromJsonModel);
推荐阅读
- vue.js - 元素 UI 表 - 添加百分比作为宽度
- php - Symfony 调试栏隐藏在模板操作上
- rabbitmq - rabbitmq 服务器磁盘空间警报
- graphql - graphql 访问对象中的项目时遇到问题
- javascript - 从表内的下拉列表中获取选定的值
- uwp - UWP 组合框滚动条可见性
- html - 从 html5 视频播放器隐藏视频下载按钮在 chrome 最新版本中不起作用 - 70.0.3538.110
- web-applications - 如何限制/拒绝对应用系统管理员的数据访问
- cloud-foundry - Swisscom Cloud Foundry:有没有办法请求应用实例在不同的区域运行?
- python - Osmnx 绘制多个图形路径