【dart学习】--Dart之JSON
概述
  现在很难想象移动应⽤程序不需要与后台交互或者存储结构化数据。现在开发,数据传输⽅式基本都是⽤JSON,在Flutter中是没
有GSON/Jackson/Moshi这些库,因为这些库需要运⾏时反射,在Flutter是禁⽤的。运⾏时反射会⼲扰Dart的_tree shaking_。使⽤_tree shaking_,可以在发版是"去除"未使⽤的代码,来优化软件的⼤⼩。由于反射会默认使⽤所有代码,因此_tree shaking_会很难⼯作,这些⼯具⽆法知道哪些widget在运⾏时未被使⽤,因此冗余代码很难剥离,使⽤反射时,应⽤尺⼨⽆法轻松进⾏优化,虽然不能在Flutter使⽤运⾏时反射,但有些库提供了类型简单易⽤的API,但它们是基于代码⽣成的。下⾯学学在Flutter中如何操作JSON数据的使⽤JSON有两个常规策略:
1. ⼿动序列化和反序列化
2. 通过代码⽣成⾃动序列化和反序列化不同的项⽬有不同的复杂度和场景,针对于⼩的项⽬,使⽤代码⽣成器可能会杀猪⽤⽜⼑了。对
于具有多个JSON model的复杂应⽤程序,⼿动序列化可能会⽐较繁琐,且容易出错。
1.⼿动序列化JSON
Flutter中基本的JSON序列化⾮常简单,Flutter有⼀个内置的dart:convert库,其中包含⼀个简单的JSON解码器和编码器。下⾯简单实现⼀下:
1.1.内连序列化JSON
⾸先记得导库:
import 'dart:convert';
然后根据字符串解析:
//内连序列化JSON
decodeJson() {
var data= '{"name": "Knight","email": "Knight@163"}';
Map<String,dynamic> user = json.decode(data);
//输出名字
print("Hello,my name is ${user['name']}");
//输出邮箱
print("Hello,This is my email ${user['email']}");
}
结果输出:
I/flutter ( 5866): Hello,my name is Knight
I/flutter ( 5866): Hello,This is my email Knight@163
  这样,可以获得我们想要的数据了,我觉得这种⽅法很实⽤⼜能简单理解,但是不幸的是,JSON.decode()仅返回⼀
个Map<String,dynamci>,这意味着当直到运⾏才知道值的类型,这种⽅法会失去⼤部分静态类型语⾔特性:类型安全、⾃动补全和编译时异常。这样的话,代码变得⾮常容易出错,就好像上⾯我们访问name字段,打字打错了,达成namr。但是这个JSON在map结构中,编译器不知道这个错误的字段名(编译时不会报错)。为了解决所说的问题,模型类中序列化JSON的作⽤出来了。
1.2.模型类中序列化JSON
通过引⼊⼀个简单的模型类(model class)来解决前⾯提到的问题,建⽴⼀个User类,在类内部有两个⽅法:
1. User.fromJson构造函数,⽤于从⼀个map构造出⼀个User实例map structure
2. toJson⽅法,将User实例化⼀个map 这样调⽤的代码就具有类型安全、⾃动补全和编译时异常,当拼写错误或字段类型视为其他类型,
程序不会通过编译,那就避免运⾏时崩溃。
1.2.1.user.dart
新建⼀个model⽂件夹,⽤来放实体,在其⽂件下新建User.dart:
class User {
final String name;
final String email;
User(this.name, ail);
User.fromJson(Map<String, dynamic> json)
: name = json['name'],
email = json['email'];
Map<String, dynamic> toJson() =>
{
'name': name,
'email': email,
}
调⽤如下:
import 'model/User.dart';//记得添加
.
...
//使⽤模型类反序列化
decodeModelJson(){
var data= '{"name": "Knight","email": "Knight@163"}';
Map userMap = json.decode(data);
var user = new User.fromJson(userMap);
//打印出名字
print("Hello,my name is ${user.name}");
//打印出邮箱
print("Hello,my name is ${ail}");
}
把序列化逻辑到移到模型本⾝内部,采⽤这种⽅法,反序列化数据就很简单了。序列化⼀个user,只是将User对象传递给该de⽅法:
flutter pub
//序列化⼀个user
encodeModelJson(){
var user = new User("Knight","Knight163");
String user_json = de(user);
print(user_json);
}
结果输出:
I/flutter ( 6684): {"name":"Knight","email":"Knight163"}
2.使⽤代码⽣产库序列化JSON
下⾯使⽤json_serializable package包,它是⼀个⾃动化的源代码⽣成器,可以为开发者⽣成JSON序列化魔板。
2.1.添加依赖
要包含json_serializable到项⽬中,需要⼀个常规和两个开发依赖项,开发依赖项是不包含在应⽤程序源代码中的依赖项:
dependencies:
# Your other regular dependencies here
json_annotation: ^2.0.0
dev_dependencies:-->开发依赖项
# Your other dev_dependencies here
build_runner: ^1.1.3 -->最新版本1.2.8 因为我sdk版本⽐较低所以⽤低版本
json_serializable: ^2.0.2
2.2.代码⽣成
有两种运⾏代码⽣成器的⽅法:
1. ⼀次性⽣成,在项⽬根⽬录运⾏flutter packages pub run build_runner build,可以在需要为我们的model⽣成json序列化代码。这触发⼀次性构
建,它通过源⽂件,挑选相关的并为它们⽣成必要的序列化代码。这个⾮常⽅便,但是如果我们不需要每次在model类中进⾏更改都要⼿动运⾏构建命令的话会更好。
2. 持续⽣成,使⽤_watcher_可以使源代码⽣成的过程更加⽅便,它会监视项⽬中⽂化的变化,并在需要时⾃动构建必要的⽂件,通
过flutter packages pub run build_runner watch在项⽬根⽬录运⾏启动_watcher_,只需启动⼀次观察器,然后并让它在后台运⾏,这是安全的。
将上⾯的User.dart修改成下⾯:
import 'package:json_annotation/json_annotation.dart';
part 'dart';-->⼀开始爆红
//这个标注是告诉⽣成器,这个类是需要⽣成Model类的
@JsonSerializable()
class User{
User(this.name, ail);
String name;
String email;
factory User.fromJson(Map<String, dynamic> json){--->⼀开始爆红
return _$UserFromJson(json);
}
Map<String, dynamic> toJson() { --->⼀开始爆红
return _$UserToJson(this);
}
下⾯就⽤⼀次性⽣成命令,在项⽬根⽬录打开命令⾏执⾏:
最后发现会在当前⽬录⽣成dart⽂件:
⾥⾯的内容可以⾃⼰去看看看,就是反序列化/序列化的操作。注意:没⽣成dart执⾏多⼏次命令即可。最后通过json_serializable⽅式反序列化JSON字符串,不需要对先前代码修改:
2.3.反序列化
var data= '{"name": "Knight","email": "Knight@163"}';
Map userMap = json.decode(data);
var user = new User.fromJson(userMap);
/
/打印出名字
print("Hello,my name is ${user.name}");
//打印出邮箱
print("Hello,my name is ${ail}");
2.4.序列化
var user = new User("Knight","Knight163");
String user_json = de(user);
print(user_json);
结果是跟上⾯⼀样,不过这种⽅式额外多了⽣成⼀个⽂件...

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。