因为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
很好用。整体推荐使用后两种,能够大大提高开发效率,不用埋头去搞一些重复的序列化工做。