# 序列化
编码 和 序列化数据 是一回事——将数据结构转换为字符串。
解码 和 反序列化数据 则是相反的过程——将字符串转换为数据结构。然而,序列化数据 通常也指代将数据结构转换为更加易读的数据格式的整个过程。
目的:
// 平时使用map数据
map['key1']['key2']
// 但是,如果把map映射到一个class,就可以这样用
mapclass.key1.key2
# 前置准备工作
安装插件flutter helppers
:
需要添加依赖:
dependencies:
# 序列化
json_annotation: ^4.1.0
dev_dependencies:
json_serializable: ^5.0.2
build_runner: ^2.1.4
使用flutter pub get
安装依赖。
# 创建模型文件夹
Entity文件夹用于存放后续helpers自动产生的所有的模型文件 -> 主要目的是json转class,class转json互转。
创建一个send_code.dart
的文件:
方法一、手动方式:
使用
jsc
快速创建json_serilizable的结构合作
jsf
快速创建相关联的.g.dart
的文件import 'package:json_annotation/json_annotation.dart'; part 'send_code_response.g.dart'; () class SendCodeResponse { SendCodeResponse(); factory SendCodeResponse.fromJson(Map<String, dynamic> json) => _$SendCodeResponseFromJson(json); Map<String, dynamic> toJson() => _$SendCodeResponseToJson(this); }
方法二、自动方式:
通过json数据反向生成.dart
的文件:
在线工具:
推荐工具1https://caijinglong.github.io/json2dart/index.html (opens new window)
推荐工具2https://javiercbk.github.io/json_to_dart/ (opens new window)
vscode插件市场也有插件jsontodart
。
# 创建send_code及.g
文件
使用json转dart工具产生的文件
import 'package:json_annotation/json_annotation.dart';
part 'send_code_response.g.dart';
()
class SendCodeResponse extends Object {
(name: 'code')
int code;
(name: 'result')
Result result;
SendCodeResponse(
this.code,
this.result,
);
factory SendCodeResponse.fromJson(Map<String, dynamic> srcJson) =>
_$SendCodeResponseFromJson(srcJson);
Map<String, dynamic> toJson() => _$SendCodeResponseToJson(this);
}
()
class Result extends Object {
(name: 'result')
int result;
(name: 'errmsg')
String errmsg;
(name: 'ext')
String ext;
(name: 'detail')
List<Detail> detail;
Result(
this.result,
this.errmsg,
this.ext,
this.detail,
);
factory Result.fromJson(Map<String, dynamic> srcJson) =>
_$ResultFromJson(srcJson);
Map<String, dynamic> toJson() => _$ResultToJson(this);
}
()
class Detail extends Object {
(name: 'result')
int result;
(name: 'errmsg')
String errmsg;
(name: 'mobile')
String mobile;
(name: 'nationcode')
String nationcode;
(name: 'isocode')
String isocode;
(name: 'sid')
String sid;
(name: 'fee')
int fee;
Detail(
this.result,
this.errmsg,
this.mobile,
this.nationcode,
this.isocode,
this.sid,
this.fee,
);
factory Detail.fromJson(Map<String, dynamic> srcJson) =>
_$DetailFromJson(srcJson);
Map<String, dynamic> toJson() => _$DetailToJson(this);
}
使用命令flutter pub run build_runner build
,产生send_conde_response.g.dart
文件:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'send_code_response.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SendCodeResponse _$SendCodeResponseFromJson(Map<String, dynamic> json) =>
SendCodeResponse(
json['code'] as int,
Result.fromJson(json['result'] as Map<String, dynamic>),
);
Map<String, dynamic> _$SendCodeResponseToJson(SendCodeResponse instance) =>
<String, dynamic>{
'code': instance.code,
'result': instance.result,
};
Result _$ResultFromJson(Map<String, dynamic> json) => Result(
json['result'] as int,
json['errmsg'] as String,
json['ext'] as String,
(json['detail'] as List<dynamic>)
.map((e) => Detail.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$ResultToJson(Result instance) => <String, dynamic>{
'result': instance.result,
'errmsg': instance.errmsg,
'ext': instance.ext,
'detail': instance.detail,
};
Detail _$DetailFromJson(Map<String, dynamic> json) => Detail(
json['result'] as int,
json['errmsg'] as String,
json['mobile'] as String,
json['nationcode'] as String,
json['isocode'] as String,
json['sid'] as String,
json['fee'] as int,
);
Map<String, dynamic> _$DetailToJson(Detail instance) => <String, dynamic>{
'result': instance.result,
'errmsg': instance.errmsg,
'mobile': instance.mobile,
'nationcode': instance.nationcode,
'isocode': instance.isocode,
'sid': instance.sid,
'fee': instance.fee,
};
# 调整user_service
import 'package:my_app/entity/send_code_response.dart';
// ...
Future sendCode(String mobile) async {
var params = {
'mobile': mobile,
};
// Map -> Class Class -> Map
// res['data']['code'] -> Response.data.code
// ts -> json
var res = await DioHttp().get('/public/sendcode', params);
if (res.statusCode == 200) {
Map<String, dynamic>? data = res.data;
// 请求成功
SendCodeResponse sendCodeResponse = SendCodeResponse.fromJson(data!);
if (sendCodeResponse.code != 200) {
// 发送短信验证码失败 -> 给用户一个友好的提示
// todo
} else {
// 发送成功
// todo
}
return sendCodeResponse;
}
}
这样调整完之后,再次发送请求,就可以使用sendCodeResponse
来取用响应回来的数据了。
# 常见问题
产生原因:
已经有对应的
.g.dart
的自动产生的文件了。修改过实体之后,又去使用
flutter pub run build_runner build
命令
解决方法:
- 删除
.g.dart
的文件(适合文件比较少的场景)
- 加入
--delete-conflicting-outputs
标签
注意:如果 对.g.dart的文件进行了修改,这样会覆盖之前的文件;