Flutter数据序列化插件carp_serializable的使用
Flutter数据序列化插件carp_serializable的使用
简介
carp_serializable
是一个基于 json_serializable
的 Dart 包,用于实现从 JSON 到对象的多态(polymorphic)序列化和反序列化。它通过在 JSON 中添加类型信息来支持继承类的序列化。在使用该插件之前,请确保你已经熟悉了 json_serializable
的基本用法。
入门
要在项目中使用 carp_serializable
,你需要在 pubspec.yaml
文件中添加以下依赖:
dependencies:
json_annotation: ^latest
carp_serializable: ^latest
dev_dependencies:
build_runner: any # 用于生成 JSON 序列化代码
json_serializable: any
使用方法
为了支持多态序列化,每个类需要满足以下条件:
- 继承
Serializable
类:所有需要序列化的类都必须继承自Serializable
。 - 使用
@JsonSerializable
注解:为类添加@JsonSerializable
注解。 - 实现三个 JSON 方法:
Function get fromJsonFunction => ...
:返回从 JSON 反序列化的函数。factory ...fromJson(...)
:工厂构造函数,用于从 JSON 创建对象。Map<String, dynamic> toJson() => ...
:将对象转换为 JSON 的方法。
- 注册类到
FromJsonFactory
:在应用程序启动时,将类注册到FromJsonFactory
单例中。 - 生成序列化代码:使用
flutter pub run build_runner build --delete-conflicting-outputs
命令生成fromJson
和toJson
方法。
示例代码
以下是一个完整的示例,展示了如何使用 carp_serializable
进行多态序列化和反序列化。
import 'package:carp_serializable/carp_serializable.dart';
import 'package:json_annotation/json_annotation.dart';
// Auto generate json code (.g files) with:
// dart run build_runner build --delete-conflicting-outputs
part 'example.g.dart';
/// 基础类 A
@JsonSerializable()
class A extends Serializable {
int index;
A([this.index = 0]) : super();
@override
Function get fromJsonFunction => _$AFromJson;
factory A.fromJson(Map<String, dynamic> json) =>
FromJsonFactory().fromJson<A>(json);
@override
Map<String, dynamic> toJson() => _$AToJson(this);
}
/// 继承自 A 的类 B
///
/// 该类展示了三个非默认行为:
/// * 可为空的字符串 [str] 不会包含在 JSON 中,因为 [includeIfNull] 设置为 false
/// * 拥有自定义的 [jsonType] 类型名称
/// * 在 [fromJson] 工厂方法中提供了 [notAvailable] 参数,指定如果未注册 fromJson 方法时的默认值
@JsonSerializable(includeIfNull: false)
class B extends A {
String? str;
B([super.index, this.str]) : super();
@override
String get jsonType => 'dk.carp.$runtimeType';
@override
Function get fromJsonFunction => _$BFromJson;
factory B.fromJson(Map<String, dynamic> json) =>
FromJsonFactory().fromJson<B>(json, notAvailable: B(-1));
@override
Map<String, dynamic> toJson() => _$BToJson(this);
}
/// 包含另一个可序列化类 B 的类 C
///
/// 注意 [explicitToJson] 必须设置为 true,以便通过 [toJson] 方法进行“深度”JSON 序列化
@JsonSerializable(explicitToJson: true)
class C extends A {
B b;
C(super.index, this.b) : super();
@override
Function get fromJsonFunction => _$CFromJson;
factory C.fromJson(Map<String, dynamic> json) =>
FromJsonFactory().fromJson<C>(json);
@override
Map<String, dynamic> toJson() => _$CToJson(this);
}
void main() {
// 记得在 JSON Factory 中注册反序列化函数
FromJsonFactory().register(A());
FromJsonFactory().register(B());
FromJsonFactory().register(C(0, B()));
// 也可以使用不同的 jsonType 注册 B
FromJsonFactory().register(B(1), type: 'B');
A a = A(1);
B b = B(2, 'abc');
C c = C(3, b);
print(toJsonString(a)); // 输出 A 的 JSON
print(toJsonString(b)); // 输出 B 的 JSON
print(toJsonString(c)); // 输出 C 的 JSON
A newA = A.fromJson(a.toJson());
B newB = B.fromJson(b.toJson());
// 注意以下代码只有在 C 类注解中设置了 "explicitToJson" 为 true 时才有效
// 这确保了 JSON 的“深度”转换
C newC = C.fromJson(c.toJson());
print(toJsonString(newA.toJson())); // 输出反序列化后的 A 的 JSON
print(toJsonString(newB.toJson())); // 输出反序列化后的 B 的 JSON
print(toJsonString(newC.toJson())); // 输出反序列化后的 C 的 JSON
}
关键点解释
-
多态序列化:通过在 JSON 中添加
__type
字段,carp_serializable
支持多态类的序列化。例如,A
和B
类的 JSON 输出如下:{ "__type": "A", "index": 1 } { "__type": "B", "index": 2, "str": "abc" }
-
自定义类型名称:你可以通过重写
jsonType
属性来自定义 JSON 中的类型名称。例如,B
类可以使用dk.carp.B
作为类型名称:{ "__type": "dk.carp.B", "index": 2, "str": "abc" }
-
嵌套类:
C
类包含了一个B
类实例。为了支持嵌套类的序列化,你需要在@JsonSerializable
注解中设置explicitToJson: true
。这样可以确保C
类的toJson
方法能够正确地序列化其内部的B
类实例。{ "__type": "C", "index": 3, "b": { "__type": "dk.carp.B", "index": 2, "str": "abc" } }
更多关于Flutter数据序列化插件carp_serializable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter数据序列化插件carp_serializable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 carp_serializable
插件进行数据序列化的 Flutter 代码示例。carp_serializable
是一个用于 Flutter 和 Dart 的序列化库,特别适用于需要复杂对象序列化和反序列化的场景,比如科学研究数据收集应用。
首先,确保你已经在 pubspec.yaml
文件中添加了 carp_serializable
依赖:
dependencies:
flutter:
sdk: flutter
carp_serializable: ^x.y.z # 替换为最新版本号
然后,运行 flutter pub get
来获取依赖。
接下来,我们创建一个简单的示例,展示如何使用 carp_serializable
插件。
步骤 1: 定义数据模型
首先,定义一个数据模型,并使用 @CarpSerializable()
注解标记它。
import 'package:carp_serializable/carp_serializable.dart';
part 'data_model.g.dart'; // 这将生成序列化代码
@CarpSerializable()
class Person {
String name;
int age;
Person({required this.name, required this.age});
// 从生成的代码中使用 factory 构造函数进行反序列化
factory Person.fromMap(Map<String, dynamic> map) => _$PersonFromJson(map);
// 使用生成的代码进行序列化
Map<String, dynamic> toMap() => _$PersonToJson(this);
}
步骤 2: 生成序列化代码
在项目根目录下运行以下命令以生成序列化代码:
flutter pub run build_runner build
这将在你的项目目录中生成一个 data_model.g.dart
文件,其中包含序列化所需的代码。
步骤 3: 使用序列化和反序列化
现在,你可以使用 toMap()
方法序列化对象,并使用 fromMap()
方法反序列化对象。
void main() {
// 创建一个 Person 对象
Person person = Person(name: 'Alice', age: 30);
// 序列化对象
Map<String, dynamic> personMap = person.toMap();
print('Serialized Person: $personMap');
// 反序列化对象
Person deserializedPerson = Person.fromMap(personMap);
print('Deserialized Person: ${deserializedPerson.name}, Age: ${deserializedPerson.age}');
}
完整示例
以下是完整的代码示例,包括模型定义、生成代码命令以及使用示例:
data_model.dart
import 'package:carp_serializable/carp_serializable.dart';
part 'data_model.g.dart';
@CarpSerializable()
class Person {
String name;
int age;
Person({required this.name, required this.age});
factory Person.fromMap(Map<String, dynamic> map) => _$PersonFromJson(map);
Map<String, dynamic> toMap() => _$PersonToJson(this);
}
main.dart
import 'data_model.dart';
void main() {
Person person = Person(name: 'Alice', age: 30);
Map<String, dynamic> personMap = person.toMap();
print('Serialized Person: $personMap');
Person deserializedPerson = Person.fromMap(personMap);
print('Deserialized Person: ${deserializedPerson.name}, Age: ${deserializedPerson.age}');
}
pubspec.yaml(部分)
dependencies:
flutter:
sdk: flutter
carp_serializable: ^x.y.z # 替换为最新版本号
dev_dependencies:
build_runner: ^x.y.z # 确保安装了 build_runner
确保你已经安装了 build_runner
,因为在生成序列化代码时需要用到它。
通过上述步骤,你就可以在 Flutter 项目中使用 carp_serializable
插件进行数据序列化和反序列化了。