build value使用介绍
实际开发过程中,不可避免的要和服务端进行数据交互。json 是一种可读性强应用广泛的协议。Java 语言中,有 Gson,Jackson,fastjson 这样的序列化包,但 Dart 里没有。这是因为这些包实现序列化依赖反射,而反射与缩小包体积的算法tree shaking相冲突。所以在 Dart 里使用 build_value 这样的工具生成序列化的代码。
1.添加依赖
build_value 是一个三方包,和 Java 里面的 Lombok 有点类似,需要添加以下依赖。
dependencies:
built_collection: ^5.0.0
built_value: ^8.4.0
dev_dependencies:
build_runner: ^1.0.0
built_value_generator: ^8.4.0
2. 配置Vs Code代码模板
build_value 会自动识别需要生成代码的类,这些类的格式固定。在 Vs Code 里可以配置模板:文件→首选项→配置用户代码片段,搜索dart.json
,将下面的内容拷贝进去。
{
"Built Value": {
"prefix": "blt",
"body": [
"abstract class ${1} implements Built<${1}, ${1}Builder> {",
"\t${0:// fields go here}",
"",
"\t${1}._();",
"",
"\tfactory ${1}([updates(${1}Builder b)]) = _$${1};",
"}"
],
"description": "Built Value Class"
},
"Built Value Serializable": {
"prefix": "blts",
"body": [
"abstract class ${1} implements Built<${1}, ${1}Builder> {",
"\t${0:// fields go here}",
"",
"\t${1}._();",
"",
"\tfactory ${1}([updates(${1}Builder b)]) = _$${1};",
"",
"\tString toJson() {",
"\t\treturn json.encode(serializers.serializeWith(${1}.serializer, this));",
"\t}",
"",
"\tstatic ${1}? fromJson(String jsonString) {",
"\t\treturn serializers.deserializeWith(${1}.serializer, json.decode(jsonString));",
"\t}",
"",
"\tstatic Serializer<${1}> get serializer => _$${1/(^[A-z]{1})/${1:/downcase}/}Serializer;",
"}"
],
"description": "Serializable Built Value Class"
},
"Built Value Header": {
"prefix": "blth",
"body": [
"library ${1};",
"",
"import 'dart:convert';",
"",
"import 'package:built_collection/built_collection.dart';",
"import 'package:built_value/built_value.dart';",
"import 'package:built_value/serializer.dart';",
"",
"part '${1}.g.dart';",
],
"description": "Built Value Imports and File Header"
},
}
3. 编写代码
新建一个 person.dart 文件,输入blth
,插件自动补充 build_value 的头。
输入blt
会补充内容。
执行命令flutter packages pub run build_runner build
即可完成自动生成。此时目录下会多出一个 person.g.dart 文件。
build_value 支持监控文件变化,自动生成代码。使用命令flutter packages pub run build_runner watch
即可
4. builder使用
这里定义了person
类,它包含了两个属性:name
和address
。
abstract class Person implements Built<Person, PersonBuilder> {
// fields go here
String get name;
String get address;
Person._();
factory Person([updates(PersonBuilder b)]) = _$Person;
}
使用时,传入一个 builder 到构造函数中。这里..
被称为级联操作符。
Person p = Person((b) => b
..name = "lily"
..address = "jiangxi");
如果 builder 没有指定某个属性的值,此时程序会崩溃。需要在可以为空的属性前加上?
。
abstract class Person implements Built<Person, PersonBuilder> {
// fields go here
String? get name;
String get address;
Person._();
factory Person([updates(PersonBuilder b)]) = _$Person;
}
5. rebuild生成新对象
build_value 没有 setter 方法,如果想修改某些属性,可以使用rebuild
方法重新生成一个对象。
Person q = p.rebuild((b) => b..address = "sichuang");
6. build collectoin使用
当属性值为集合时,可以使用 build_value 里的 build collcetion 。定义属性类型时,需要指定集合,下面例子定义了phones
这个 list 和bags
这个 set。
abstract class Person implements Built<Person, PersonBuilder> {
// fields go here
String? get name;
String get address;
BuiltList<String> get phones;
BuiltSet<String> get bags;
Person._();
factory Person([updates(PersonBuilder b)]) = _$Person;
}
使用时,可以向对应的集合添加所需的元素。
Person p = Person((b) => b
..address = "jiangxi"
..name = "lily"
..bags.addAll(['bag1', 'bag2'])
..phones.addAll(['phone1', 'phone2']));
7. serializer使用
和前面类似,在Vs code 里输入blts
,插件就会自动补全代码。输入类名之后记得按下tab
,这样serializer
才会变成驼峰结构。
接下来需要新建serializers.dart
,和模型类似,先使用blth
声明头信息。然后定义serializer
。
library serializers;
import 'dart:convert';
import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:flutter_application_1/model/student.dart';
part 'serializers.g.dart';
@SerializersFor([Student])
final Serializers serializers = _$serializers;
这时就可以在其他地方使用toJson
和fromJson
方法了。
void main() {
Student s = Student((b) => b
..name = "lily"
..address = "qinhai");
print(s.toJson());
}
8. 使用标准json序列化
细心的读者会发现,build_value 序列化方式和标准的序列化方式不一样,可以修改serializer
,使用标准的序列化方式。
@SerializersFor([Student])
final Serializers serializers =
(_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();