因爲Flutter
禁用運行時反射,因此在Flutter
中是沒有GSON
,Jackson
這類解析JSON
的庫。官方解釋運行時反射會干擾Dart
的_tree shaking_
。使用_tree shaking_
咱們能夠在發版時去除未使用的代碼。這能夠顯着優化應用程序的大小。 因爲反射會默認使用全部代碼,所以_tree shaking_
會很難工做。這些工具沒法知道哪些widget
在運行時未被使用,所以冗餘代碼很難剝離。使用反射時,應用尺寸沒法輕鬆的進行優化。html
使用Flutter
內置的dart:convert
庫作基本的JSON
序列化很簡單:git
Map<String, dynamic> person = JSON.decode(json); print('${person['name']}'); print('${person['age']'); 複製代碼
JSON.decode()
返回一個Map<String, dynamic>
,這意味着咱們直到運行時才知道值的類型。這種方法,咱們失去了靜態類型語言特性,代碼很是容易出錯。不推薦。github
固然咱們也能夠手動在模型類中序列化JSON
:json
class Person { final String name; final String age; User(this.name, this.age); User.fromJson(Map<String, dynamic> json) : name = json['name'], age = json['age']; Map<String, dynamic> toJson() => { 'name': name, 'age': age, }; } 複製代碼
Map personMap = JSON.decode(json); var person = new Person.fromJson(personMap); print('${person.name}'); print('${person.age}'); 複製代碼
這樣咱們調用代碼能夠具備類型安全、自動補全字段以及編譯時異常等靜態類型語言特性。若是拼寫或者類型錯誤就不會經過編譯,而不是在運行時崩潰。安全
在項目實戰中JSON
對象不多會這麼簡單,各類List
和Map
嵌套的JSON
也是很常見的。如何安全且高效的JSON
轉Model
纔是咱們想要的。bash
json_serializable是一個自動化的源代碼生成器,能夠爲咱們生成JSON
序列化模板。在pubspec.yaml
中添加依賴並執行flutter pub get
:markdown
dependencies:
json_annotation: ^3.0.0
dev_dependencies:
build_runner: ^1.0.0
json_serializable: 3.2.0
複製代碼
這裏沒有使用最新版本由於咱們Flutter
版本爲v1.9.1+hotfix.6
,Dart
版本比較低。app
生成模型類咱們使用一位大佬寫的json2dart工具。工具
假設mock
了一個JSON
:oop
[ { "name": "小龍女", "age": "18", "tele": "13888888888" }, { "name": "楊過", "age": "18", "tele": "13666666666" }, { "name": "尹志平", "age": "18", "tele": "13333333333" } ] 複製代碼
工具使用很簡單直接粘貼生成對應的類名稱
此時咱們將生成的代碼copy
出來粘在咱們建立的模型類中。
import 'package:json_annotation/json_annotation.dart'; part 'person_model.g.dart'; List<PersonModel> getPersonModelList(List<dynamic> list){ List<PersonModel> result = []; list.forEach((item){ result.add(PersonModel.fromJson(item)); }); return result; } @JsonSerializable() class PersonModel extends Object { @JsonKey(name: 'name') String name; @JsonKey(name: 'age') String age; @JsonKey(name: 'tele') String tele; PersonModel(this.name,this.age,this.tele,); factory PersonModel.fromJson(Map<String, dynamic> srcJson) => _$PersonModelFromJson(srcJson); Map<String, dynamic> toJson() => _$PersonModelToJson(this); } 複製代碼
這裏須要注意這個工具可能有少字段的狀況,若是是List
的JSON
只會取其中的第一個(小龍女)來生成模型的字段。也就是若是後面的Item
(楊過,尹志平)字段數量大於第一個也會按照第一個的字段來生成。
上面的模型類生成以後會先報錯,由於模型類的生成代碼還不存在,因此咱們須要運行代碼生成器來爲咱們生成序列化模板。
flutter packages pub run build_runner build
。flutter packages pub run build_runner watch
。這裏選擇哪一種方式取決於你的改動頻率,推薦使用watch
的方式。
Map personList = JSON.decode(json);
var list = getPersonModelList(personList);
複製代碼
json_serializable
這種方式,咱們能夠輕鬆的生成一個模型類。經過源代碼生成器建立一個g.dart
的文件,它具備全部必需的序列化邏輯。
app.quicktype.io是一個將JSON
轉換成模型類的工具網站,目前來看支持大部分經常使用語言,而且靈活的可選項也很是多:
這裏咱們仍是用上面的JSON
作一下嘗試:
生成的模型類是使用了Flutter
內置的dart:convert
作序列化。
// To parse this JSON data, do // // final personModel = personModelFromJson(jsonString); import 'dart:convert'; List<PersonModel> personModelFromJson(String str) => List<PersonModel>.from(json.decode(str).map((x) => PersonModel.fromJson(x))); String personModelToJson(List<PersonModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson()))); class PersonModel { String name; String age; String tele; PersonModel({ this.name, this.age, this.tele, }); factory PersonModel.fromJson(Map<String, dynamic> json) => PersonModel( name: json["name"], age: json["age"], tele: json["tele"], ); Map<String, dynamic> toJson() => { "name": name, "age": age, "tele": tele, }; } 複製代碼
能夠看到這個模型類正是咱們須要的,使用方式也在上面註釋的很清楚,目前來說這種方式操做起來會比使用json_serializable
操做起來更簡便一些。
json_serializable
:效率高,watch
很好用。整體推薦使用後兩種,能夠大大提高開發效率,不用埋頭去搞一些重複的序列化工做。