背景
在開發(fā)過程中芝发,服務端通常返回的是JSON格式的數(shù)據庶艾,對于Web開發(fā)人員(JavaScript、TypeScript)中,可以直接拿到JSON數(shù)據來做我們的邏輯色解。
JSON本身起源于JavaScript痘昌,JavaScript解析處理JSON有天然的優(yōu)勢
但在像 Java钥勋、Dart 等強類型語言中炬转,我們需要將JSON數(shù)據轉模型對象來使用。
一般情況下算灸,我們會使用一些第三方庫來動態(tài)轉化Model,但是Flutter中沒有像Java的GSON/Jackson這類JSON序列化庫扼劈。
因為Flutter中禁用運行時反射。官方解釋是運行時反射會干擾Dart的Tree Shaking,使用Tree Shaking可以在Release版中去除未使用的代碼菲驴,這可以顯著優(yōu)化應用程序的大小荐吵。
由于反射會默認應用到Dart的反射功能,而正因如此也就無法實現(xiàn)動態(tài)化轉Model的功能赊瞬。
序列化的幾種方案
Flutter官方推薦的有兩種序列化方案:https://flutterchina.club/json/
-
小項目手動序列化先煎,這種方案比較簡單,比較適合小項目簡單的JSON轉換巧涧,但項目龐大薯蝎,或者多人合作,容易出錯谤绳,也不易維護占锯。
Flutter有一個內置dart:convert庫 使用 dart:convert手動序列化JSON
-
在大中型項目中使用代碼生成,需要用到以下三個依賴包缩筛,通過代碼自動生成的方式消略,生成模型。這種方案易維護瞎抛,由于序列化數(shù)據代碼不再需要手動編寫或者維護艺演,你可以將序列化 JSON 數(shù)據在運行時的異常風險降到最低;
轉換流程
- 在pubspec.yaml中添加依賴
json_annotation: ^3.1.0
json_serializable: ^3.5.0
build_runner: ^1.0.0
[圖片上傳失敗...(image-b6fc38-1605061601267)]
在Android Stuido中執(zhí)行Pub get
- 新建模型類(mode/demo_model.dart)
class DemoModel{
}
-
在網頁上把后端請求到的JSON數(shù)據轉換成Model:
https://czero1995.github.io/json-to-model/:網站轉換支持無限層次嵌套復雜對象的轉換
- 比如將以下JSON數(shù)據復制到網頁上(左邊):
{
"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數(shù)據(右邊)
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);
}
再將轉換之后的數(shù)據復制出來覆蓋到demo_model.dart文件上
- 執(zhí)行build_runner
在項目終端下執(zhí)行命令:
flutter pub run build_runner build
執(zhí)行完成后婿失,會生成demo_model.g.dart文件