背景
在开发过程中,服务端通常返回的是JSON格式的数据,对于Web开发人员(JavaScript、TypeScript)中,可以直接拿到JSON数据来做我们的逻辑。
代码语言:javascript复制JSON本身起源于JavaScript,JavaScript解析处理JSON有天然的优势
但在像 Java、Dart 等强类型语言中,我们需要将JSON数据转模型对象来使用。
- 一般情况下,我们会使用一些第三方库来动态转化Model,但是Flutter中没有像Java的GSON/Jackson这类JSON序列化库。
- 因为Flutter中禁用运行时反射。官方解释是运行时反射会干扰Dart的Tree Shaking,使用Tree Shaking可以在Release版中去除未使用的代码,这可以显著优化应用程序的大小。
- 由于反射会默认应用到Dart的反射功能,而正因如此也就无法实现动态化转Model的功能。
序列化的几种方案
Flutter官方推荐的有两种序列化方案:https://flutterchina.club/json/
小项目手动序列化,这种方案比较简单,比较适合小项目简单的JSON转换,但项目庞大,或者多人合作,容易出错,也不易维护。
代码语言:javascript复制Flutter有一个内置dart:convert库
使用 dart:convert手动序列化JSON
在大中型项目中使用代码生成,需要用到以下三个依赖包,通过代码自动生成的方式,生成模型。这种方案易维护,由于序列化数据代码不再需要手动编写或者维护,你可以将序列化 JSON 数据在运行时的异常风险降到最低;
- json_annotation
- json_serializable
- build_runner
转换流程
- 在pubspec.yaml中添加依赖
json_annotation: ^3.1.0
json_serializable: ^3.5.0
build_runner: ^1.0.0
在Android Stuido中执行Pub get
- 新建模型类(mode/demo_model.dart)
class DemoModel{
}
- 在网页上把后端请求到的JSON数据转换成Model:https://czero1995.github.io/json-to-model/:网站转换支持无限层次嵌套复杂对象的转换
- 比如将以下JSON数据复制到网页上(左边):
{
"code": 0,
"data": {
"avatar": "xxx.png",
"id": 7,
"float":0.1,
"is_deleted": false,
"nickname": "nickName",
"openId": null,
"phone": "13641418383",
"store_ids": [1,2],
"updated": "2020-11-05 11:53:10",
"more":[{"a":1,"b":"b","c":{"c1":0.2,"c2":2}}]
}
}
- 然后转换成Model数据(右边)
import 'package:json_annotation/json_annotation.dart';
part 'demo_model_data.g.dart';
@JsonSerializable(explicitToJson: true)
class DemoModelModel {
DemoModelData data;
DemoModelModel({
this.data,
this.code,
this.message
});
factory DemoModelModel.fromJson(Map<String, dynamic> json) => _$DemoModelModelFromJson(json);
Map<String, dynamic> toJson() => _$DemoModelModelToJson(this);
}
@JsonSerializable(explicitToJson: true)
class DemoModelData {
String avatar;
int id;
double float;
bool is_deleted;
String nickname;
var openId;
String phone;
List<int> store_ids;
String updated;
List<MoreData> more;
DemoModelData({
this.avatar,
this.id,
this.float,
this.is_deleted,
this.nickname,
this.openId,
this.phone,
this.store_ids,
this.updated,
this.more,
});
factory DemoModelData.fromJson(Map<String, dynamic> json) => _$DemoModelDataFromJson(json);
Map<String, dynamic> toJson() => _$DemoModelDataToJson(this);
}
@JsonSerializable(explicitToJson: true)
class MoreData{
int a;
String b;
CData c;
MoreData({
this.a,
this.b,
this.c,
});
factory MoreData.fromJson(Map<String, dynamic> json) => _$MoreDataFromJson(json);
Map<String, dynamic> toJson() => _$MoreDataToJson(this);
}
@JsonSerializable(explicitToJson: true)
class CData{
double c1;
int c2;
CData({
this.c1,
this.c2,
});
factory CData.fromJson(Map<String, dynamic> json) => _$CDataFromJson(json);
Map<String, dynamic> toJson() => _$CDataToJson(this);
}
再将转换之后的数据复制出来覆盖到demo_model.dart文件上
- 执行build_runner
在项目终端下执行命令:
代码语言:javascript复制flutter pub run build_runner build
执行完成后,会生成demo_model.g.dart文件