在Flutter中使用JsonSerializable时如何在泛型数据模型中传递自定义参数名?
在Flutter中使用JsonSerializable时如何在泛型数据模型中传递自定义参数名?
嘿,我完全懂你的需求——你不想把param字段对应的JSON键名硬写成固定的"statistics",而是希望能根据不同场景自定义这个键名,同时还要保留JsonSerializable的泛型支持对吧?其实这个问题很好解决,咱们只需要给fromJson和toJson方法加个可选参数来传递自定义键名就行,下面一步步来给你演示:
首先,咱们修改你的DataModel类,给fromJson工厂方法新增一个paramKey参数(默认值设为你原来的"statistics",这样不传入的时候也能正常用),同时在toJson方法里也做对应的修改:
import 'package:json_annotation/json_annotation.dart'; part 'data_model.g.dart'; @JsonSerializable(genericArgumentFactories: true) class DataModel<T, P> { final int? total; final List<T> items; final P? param; DataModel({ this.total, required this.items, this.param, }); // 新增paramKey参数,支持自定义JSON键名 factory DataModel.fromJson( Map<String, dynamic> json, T Function(Object?) fromJsonT, P Function(Object?) fromJsonP, { String paramKey = "statistics", // 默认使用原来的键名 }) { final List<dynamic> itemsJson = json['items'] as List<dynamic>; final List<T> items = itemsJson .map<T>((item) => fromJsonT(item as Map<String, dynamic>)) .toList(); // 根据传入的paramKey获取对应JSON值 final dynamic paramJson = json[paramKey]; final P? param = paramJson != null ? fromJsonP(paramJson) : null; return DataModel( total: json['total'] as int?, items: items, param: param, ); } // 同样给toJson添加paramKey参数,支持自定义序列化键名 Map<String, dynamic> toJson( Object Function(T) toJsonT, Object Function(P) toJsonP, { String paramKey = "statistics", }) { return { 'total': total, 'items': items.map(toJsonT).toList(), // 只有param不为空时才添加这个键值对 if (param != null) paramKey: toJsonP(param), }; } }
接下来,咱们看看怎么用这个修改后的模型。假设你有两个子模型User和Statistics:
@JsonSerializable() class User { final String name; User(this.name); factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); Map<String, dynamic> toJson() => _$UserToJson(this); } @JsonSerializable() class Statistics { final int count; Statistics(this.count); factory Statistics.fromJson(Map<String, dynamic> json) => _$StatisticsFromJson(json); Map<String, dynamic> toJson() => _$StatisticsToJson(this); }
现在你既可以用默认的"statistics"键名解析,也可以自定义键名,比如"metadata":
// 使用默认键名"statistics"解析JSON final defaultJson = { 'total': 2, 'items': [{'name': 'Alice'}, {'name': 'Bob'}], 'statistics': {'count': 10} }; final defaultDataModel = DataModel.fromJson( defaultJson, (json) => User.fromJson(json as Map<String, dynamic>), (json) => Statistics.fromJson(json as Map<String, dynamic>), ); // 使用自定义键名"metadata"解析JSON final customJson = { 'total': 3, 'items': [{'name': 'Charlie'}, {'name': 'Dave'}, {'name': 'Eve'}], 'metadata': {'count': 15} }; final customDataModel = DataModel.fromJson( customJson, (json) => User.fromJson(json as Map<String, dynamic>), (json) => Statistics.fromJson(json as Map<String, dynamic>), paramKey: "metadata", // 这里传入自定义键名 );
序列化的时候也是一样的逻辑,想输出哪个键名就传哪个:
// 序列化为带"statistics"键的JSON final defaultOutput = defaultDataModel.toJson( (user) => user.toJson(), (stats) => stats.toJson(), ); // 序列化为带"metadata"键的JSON final customOutput = customDataModel.toJson( (user) => user.toJson(), (stats) => stats.toJson(), paramKey: "metadata", );
最后提醒一下:每次修改完模型代码后,记得运行flutter pub run build_runner build命令重新生成对应的.g.dart文件,确保代码生成正确哦~
备注:内容来源于stack exchange,提问作者Oleksii Shtanko
相关产品推荐
相关产品推荐

