我正在用Flutter开发一个移动的项目,这个项目需要连接一些服务器进行REST消费服务(GET、POST、PUT、DELETE......),并且需要检索数据以及向它们发送数据,这些数据需要用JSON格式化,所以我决定使用Json序列化库2.0.3 for 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>
类型,它对于比较类的类型转换毫无用处。2我该如何解决我的困境呢?3我应该坚持json_serialization还是使用build_价值代替?在这件事上的任何帮助都将非常感激。
我的代码:
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);
}
}
}
我期望能够序列化/反序列化“最终List列表;“不管有没有“@JsonKey”,但到目前为止,我还没能找到一种方法将它强制转换成适当的json格式。
当我尝试为这个类生成代码时(使用命令“flutter packages pub run build_runner build”),我收到了以下错误:
运行JsonSerializableGenerator时出错由于T
类型,无法为list
生成fromJson
代码。提供的TypeHelper
示例均不支持定义的类型。包:json_generic.dart:11:17
╷
11 │ final List<T> list;
│ ^^^^
╵
7条答案
按热度按时间cx6n0qe31#
这里有个例子
https://github.com/dart-lang/json_serializable/blob/master/example/lib/json_converter_example.dart
// json转换器示例.dart
//主省道
结果就是
kuarbcqp2#
这是我的正确解决方案完美地为我工作。
假设我们要使用飞行模型分页模型。在这里你必须配置飞行列表。
avwztpqn3#
json_可序列化
json_serializable有几个策略1来处理泛型类型作为单个对象
T
或List<T>
(从v. 5.0.2+开始):1.帮助程序类:
JsonConverter
个1.助手方法:
@JsonKey(fromJson:, toJson:)
1.泛型参数工厂
@JsonSerializable(genericArgumentFactories: true)
1我知道。可能还有其他方法。
帮助程序类:
JsonConverter
基本思想:使用
fromJson
和toJson
方法编写一个自定义JsonConverter
类,以识别和处理我们的TypeT
字段反序列化/序列化。JsonCoverter
策略的好处是它将模型的所有反序列化/序列化逻辑封装到一个类中,该类可在需要序列化的相同模型类型的任何类中重用,并且您的toJson
、fromJson
调用不会改变,这与泛型参数工厂策略相反,在泛型参数工厂策略中,每个toJson
、fromJson
调用要求我们提供一个处理函数。我们可以使用
JsonConverter
和我们的对象进行反序列化,注解如下:T
/List<T>
字段,或T
类型的任何/所有字段)。下面是一个包含泛型类型字段
T
的json_serializable类OperationResult<T>
的示例。关于
OperationResult
类的说明:T t
。t
可以是T
类型的单个对象***或***对象的List<T>
。T
是什么类型,它都必须具有toJson()/fromJson()
方法(即,可反串行化/可串行化)。ModelConverter
**的JsonConverter
类,用于注解T t
字段。_$OperationResultFromJson<T>(json)
和_$OperationResultToJson<T>()
现在使用T
变量下面是上面的
JsonConverter
类ModelConverter
:下面是
Serializable
接口,用于实现我们的模型类,如Order
和MenuItem
(请参见上面ModelConverter
的toJson()
代码,以了解如何/为什么使用它):帮助程序方法:
@JsonKey(fromJson:, toJson:)
此注解用于使用json_serializable为类中的 * 任何 * 类型的字段指定自定义反序列化/序列化处理程序,而不仅仅是泛型类型。
因此,我们可以为泛型类型字段
T t
指定自定义处理程序,使用与上面JsonConverter示例中相同的“查看键”逻辑。下面,我们向类
OperationResultJsonKey<T>
添加了两个静态方法(在这个Stackoverflow示例中,这样命名只是为了清楚起见):_fromJson
_toJson
(这些函数也可以作为顶级函数存在于类之外。)
然后我们向JsonKey提供这两个方法:
@JsonKey(fromJson: _fromJson, toJson: _toJson)
然后,重新运行flutter或dart(
flutter pub run build_runner build
或dart run build_runner build
)的build_runner之后,json_serializable提供的生成的反序列化方法将使用这两个静态方法。泛型参数工厂
@JsonSerializable(genericArgumentFactories: true)
在最后一种反序列化/序列化的专门处理方式中,我们希望直接为
OperationResult
上对toJson()
和fromJson()
的调用提供自定义反序列化/序列化方法。这种策略可能是最灵活的(允许你指定你想要如何对每个泛型类型进行序列化处理),但是它也非常冗长,需要你在每个
toJson
/fromJson
调用上提供一个序列化处理函数。给杰森
例如,在序列化
OperationResult<Order>
时,.toJson()
调用接受一个函数,该函数告诉json_serializable * 如何 * 在序列化OperationResult<Order>
时序列化Order
字段。该辅助函数的签名为:
Object Function(T) toJsonT
所以在
OperationResult
中,我们的toJson()
存根方法(json_serializable为我们完成)从:Map<String,dynamic> toJson() => _$OperationResultToJson(this);
致:
Map<String,dynamic> toJson(Object Function(T) toJsonT) => _$OperationResultToJson<T>(this, toJsonT);
toJson()
从接受 * 零 * 个参数变为接受***函数***作为参数Order
时,函数将由json_serializable调用Object
而不是Map<String,dynamic>
,以便它还可以处理List
中的多个T
对象,例如List<OrderItem>
来自杰森
对于
OperationResult<Order>
类中使用的genericArgumentFactories
的fromJson()
端,我们需要提供一个签名函数:T Function(Object?) fromJsonT
因此,如果要反序列化/序列化的泛型类型的对象是
OperationResult<Order>
,则fromJson()
的helper函数为:static Order fromJsonModel(Object? json) => Order.fromJson(json as Map<String,dynamic>);
下面是一个使用
genericArgumentFactories
的名为OperationResultGAF
的示例类:如果
T
是一个名为Order
的类,则Order
类可以包含用于genericArgumentFactories的静态帮助器方法:请注意,上面的帮助器方法只是调用json_serializable生成的常用
toJson()
、fromJson()
存根方法。向模型类添加此类静态方法的目的是使向
OperationResultGAF.toJson()
、OperationResultGAF.fromJson()
提供这些帮助器方法变得更简洁:我们只提供它们的函数名而不是实际的函数。例如,代替:
我们可以用途:
如果
T
是List
对象,比如List<MenuItem>
,那么我们需要处理列表的helper方法。下面是添加到
MenuItem
类以处理列表的静态帮助器方法的示例:以及如何在单元测试中调用这些静态帮助器方法的示例:
46scxncf4#
如果您使用JsonSerializable和build_runner,您可以让您的模型从一个抽象类扩展,方法是在JsonSerializable生成的代码中调用_$xxxFromJson(Map〈String,dynamic〉json),如下所示。
当您连接到REST端点时,使用如下所示的工厂方法并调用模型的fromJson。
最后调用客户端的get / getList方法。
当你创建新模型时,你必须修改FromJsonModelFactory,但是如果使用dart:mirrors不是一个选项,那么实际上它工作得很好。
希望有人会觉得这个有用。
baubqpgj5#
假设我们有两个类似的JSON,它们都有泛型类型的项目列表
这就是魔术👇
那么你可以像下面这样使用它:
doinxwow6#
以下是我的方法:
要添加对新数据模型的支持,只需将其添加到Generic.fromJson:
这适用于以下任一常规对象:
或通用对象列表:
yqyhoc1h7#
我是这样做的,不需要hackey和奇怪的'peek at keys'方法,我有点惊讶地看到这个方法在documentation包中。
对典型
JsonSerializable
类的补充包括:@_Converter()
Response<T>
类之下的_Converter<T>
类这里的数据模型也是
JsonSerializable
。