对象序列化器
用于以各种方式(JSON、通用对象)序列化数据的集合。
版本:0.1.5
目前有两种数据序列化器可用
- JSON 序列化器
- 对象序列化器
JSON 序列化器 是一个标准 JSON 格式的序列化器。支持转换为更简单数据类型的类型(例如 BigInt、DateTime、Duration、Uri 等)的序列化。工作原理很简单。您自己选择数据序列化和反序列化方法,也就是说,您完全控制此过程。
对象序列化器 是任何静态(通用)复杂数据的序列化器(支持缓存),这些数据可以表示为更简单的数据。
允许您为可以在 isolat 之间或甚至在 Internet 上传输的任何数据实现序列化器。操作原理非常简单,对于每种数据类型,您都需要实现自己的对象序列化器。
实现对象序列化器也非常简单。为此,您需要以严格的顺序写入数据,然后在相同的顺序读取这些数据。
JSON
假设我们需要使用这些数据对象。
class Company {
final String name;
final Uri website;
Company({
required this.name,
required this.website,
});
}
class Customer {
final int? age;
final DateTime? birthday;
final Duration frequency;
final CustomerLevel level;
final String name;
Customer({
required this.age,
required this.birthday,
required this.frequency,
required this.level,
required this.name,
});
}
enum CustomerLevel { retail, wholesale }
class Order {
final BigInt amount;
final Company company;
final Customer customer;
final DateTime date;
final List<OrderLine> lines;
Order({
required this.amount,
required this.company,
required this.customer,
required this.date,
required this.lines,
});
}
class OrderLine {
final Product product;
final BigInt price;
final int quantity;
final BigInt total;
OrderLine({
required this.product,
required this.price,
required this.quantity,
required this.total,
});
}
class Product {
final String name;
final BigInt price;
final Map<String, double> priceRange;
Product({
required this.name,
required this.price,
required this.priceRange,
});
}
如何在不到 30 分钟的时间内为这些数据类型实现序列化器?让我们尝试一下。
class _BigIntSerializer extends JsonSerializer<BigInt> {
@override
BigInt deserialize(Deserializer deserializer, Object? value) {
final json = cast<String>(value);
return BigInt.parse(json);
}
@override
String serialize(Serializer serializer, BigInt value) {
return value.toString();
}
}
class _CompanySerializer extends JsonSerializer<Company> {
@override
Company deserialize(Deserializer deserializer, Object? value) {
final json = cast<Map>(value);
return Company(
name: deserializer.deserialize(json['name']),
website: deserializer.deserialize(json['website']),
);
}
@override
Map<String, dynamic> serialize(Serializer serializer, Company value) {
return {
'name': serializer.serialize(value.name),
'website': serializer.serialize(value.website),
};
}
}
class _CustomerLevelSerializer extends JsonSerializer<CustomerLevel> {
@override
CustomerLevel deserialize(Deserializer deserializer, Object? value) {
final json = cast<int>(value);
return CustomerLevel.values[json];
}
@override
int serialize(Serializer serializer, CustomerLevel value) {
return value.index;
}
}
class _CustomerSerializer extends JsonSerializer<Customer> {
@override
Customer deserialize(Deserializer deserializer, Object? value) {
final json = cast<Map>(value);
return Customer(
birthday: deserializer.deserialize(json['birthday']),
age: deserializer.deserialize(json['age']),
frequency: deserializer.deserialize(json['frequency']),
level: deserializer.deserialize(json['level']),
name: deserializer.deserialize(json['name']),
);
}
@override
Map<String, dynamic> serialize(Serializer serializer, Customer value) {
return {
'age': serializer.serialize(value.age),
'birthday': serializer.serialize(value.birthday),
'frequency': serializer.serialize(value.frequency),
'level': serializer.serialize(value.level),
'name': serializer.serialize(value.name),
};
}
}
class _DateTimeSerializer extends JsonSerializer<DateTime> {
@override
DateTime deserialize(Deserializer deserializer, Object? value) {
final json = cast<String>(value);
return DateTime.fromMicrosecondsSinceEpoch(int.parse(json));
}
@override
String serialize(Serializer serializer, DateTime value) {
return value.microsecondsSinceEpoch.toString();
}
}
class _DurationSerializer extends JsonSerializer<Duration> {
@override
Duration deserialize(Deserializer deserializer, Object? value) {
final json = cast<String>(value);
return Duration(microseconds: int.parse(json));
}
@override
String serialize(Serializer serializer, Duration value) {
return value.inMicroseconds.toString();
}
}
class _OrderLineSerializer extends JsonSerializer<OrderLine> {
@override
OrderLine deserialize(Deserializer deserializer, Object? value) {
final json = cast<Map>(value);
return OrderLine(
price: deserializer.deserialize(json['price']),
product: deserializer.deserialize(json['product']),
quantity: deserializer.deserialize(json['quantity']),
total: deserializer.deserialize(json['total']),
);
}
@override
Map<String, dynamic> serialize(Serializer serializer, OrderLine value) {
return {
'price': serializer.serialize(value.price),
'product': serializer.serialize(value.product),
'quantity': serializer.serialize(value.quantity),
'total': serializer.serialize(value.total),
};
}
}
class _OrderSerializer extends JsonSerializer<Order> {
@override
Order deserialize(Deserializer deserializer, Object? value) {
final json = cast<Map>(value);
return Order(
amount: deserializer.deserialize(json['amount']),
company: deserializer.deserialize(json['company']),
customer: deserializer.deserialize(json['customer']),
date: deserializer.deserialize(json['date']),
lines: deserializer.deserializeList(json['lines']),
);
}
@override
Map<String, dynamic> serialize(Serializer serializer, Order value) {
return {
'amount': serializer.serialize(value.amount),
'company': serializer.serialize(value.company),
'customer': serializer.serialize(value.customer),
'date': serializer.serialize(value.date),
'lines': serializer.serializeList(value.lines),
};
}
}
class _ProductSerializer extends JsonSerializer<Product> {
@override
Product deserialize(Deserializer deserializer, Object? value) {
final json = cast<Map>(value);
return Product(
name: deserializer.deserialize(json['name']),
price: deserializer.deserialize(json['price']),
priceRange: deserializer.deserializeMap(json['priceRange']),
);
}
@override
Map<String, dynamic> serialize(Serializer serializer, Product value) {
return {
'name': serializer.serialize(value.name),
'price': serializer.serialize(value.price),
'priceRange': serializer.serializeMap(value.priceRange),
};
}
}
class _UriSerializer extends JsonSerializer<Uri> {
@override
Uri deserialize(Deserializer deserializer, Object? value) {
final json = cast<String>(value);
return Uri.parse(json);
}
@override
String serialize(Serializer serializer, Uri value) {
return value.toString();
}
}
大约 180 行代码。考虑到您对序列化的内容和方式拥有完全的控制权,这并不算多。
让我们看看这项工作的实际结果。最简单的测试
import 'dart:convert';
import 'package:object_serializer/json_serializer.dart';
void main(List<String> args) {
final price = BigInt.from(29.99);
final order = Order(
amount: price,
company: _company,
customer: _customer,
date: DateTime.now(),
lines: [
OrderLine(
product: _product,
price: price,
quantity: 25,
total: price * BigInt.from(25))
],
);
final orders = [order, order];
final jsonObject = serializeList(orders, _collection);
final jsonString = jsonEncode(jsonObject);
final jsonObject2 = jsonDecode(jsonString);
final orders2 = deserializeList<Order>(jsonObject2, _collection);
final jsonObject3 = serializeList(orders2, _collection);
final jsonString2 = jsonEncode(jsonObject3);
final result = jsonString == jsonString2;
print(jsonString2);
print('Test passed: $result');
}
final _collection = JsonSerializerCollection()
..addSerializer(_BigIntSerializer())
..addSerializer(_CompanySerializer())
..addSerializer(_CustomerLevelSerializer())
..addSerializer(_CustomerSerializer())
..addSerializer(_DateTimeSerializer())
..addSerializer(_DurationSerializer())
..addSerializer(_OrderLineSerializer())
..addSerializer(_OrderSerializer())
..addSerializer(_ProductSerializer())
..addSerializer(_UriSerializer());
final _company = Company(
name: 'ACME Inc.',
website: Uri.parse('https://acme.com'),
);
final _customer = Customer(
age: null,
birthday: null,
frequency: Duration(days: 10),
level: CustomerLevel.wholesale,
name: 'Peter Pan',
);
final _product = Product(
name: 'The Little White Bird',
price: BigInt.from(49.99),
priceRange: {
'3': 49.99,
'10': 39.99,
'25': 29.99,
},
);
工作结果
[{“amount”:”29″,”company”:{“name”:”ACME Inc.”,”website”:”https://acme.com”},”customer”:{“age”:null,”birthday”:null,”frequency”:”864000000000″,”level”:1,”name”:”Peter Pan”},”date”:”1658504965053872″,”lines”:[{“price”:”29″,”product”:{“name”:”The Little White Bird”,”price”:”49″,”priceRange”:{“3″:49.99,”10″:39.99,”25″:29.99}},”quantity”:25,”total”:”725″}]},{“amount”:”29″,”company”:{“name”:”ACME Inc.”,”website”:”https://acme.com”},”customer”:{“age”:null,”birthday”:null,”frequency”:”864000000000″,”level”:1,”name”:”Peter Pan”},”date”:”1658504965053872″,”lines”:[{“price”:”29″,”product”:{“name”:”The Little White Bird”,”price”:”49″,”priceRange”:{“3″:49.99,”10″:39.99,”25″:29.99}},”quantity”:25,”total”:”725″}]}] 测试通过:true
对象序列化器
简单的对象序列化器示例
class _UriSerializer extends ObjectSerializer<Uri> {
@override
Uri deserialize(Deserializer deserializer) {
return Uri.parse(deserializer.readObject());
}
@override
void serialize(Serializer serializer, Uri object) {
serializer.writeObject(object.toString());
}
}
这不是 JSON 序列化器的模拟或替代品。在这种情况下,数据被序列化到一个所谓的流中,并在需要时进行缓存。
例如,您可以序列化此类数据。
typedef _ComplexType = Map<Uri, List<Tuple2<BigInt, Tuple2<int, Base?>>>>;
class A extends Base {
A(super.base);
@override
bool operator ==(other) => other is A && other.base == base;
}
class B extends Base {
final int x;
B(super.base, this.x);
@override
bool operator ==(other) => other is B && other.base == base && other.x == x;
}
class Base {
final String base;
Base(this.base);
}
例如,可以序列化此类数据。
final _ComplexType map = {
Uri.parse('package:animals'): [
Tuple2(BigInt.parse('1'), Tuple2(1, A('Hello'))),
Tuple2(BigInt.parse('2'), Tuple2(1, A('Hello'))),
],
Uri.parse('package:zoo'): [
Tuple2(BigInt.parse('1'), Tuple2(1, B('Goodbye', 41))),
Tuple2(BigInt.parse('2'), Tuple2(2, null)),
Tuple2(BigInt.parse('1'), Tuple2(1, A('Hello'))),
],
};
输出数据流
[1, 4, 2, 4, 16, 6, 8, package:animals, 9, 9, 2, 12, 11, 14, 15, 16, 8, 1, 19, 12, 21, 2, 1, 24, 13, 26, 8, Hello, 29, 11, 31, 15, 33, 8, 2, 36, 12, 21, 39, 13, 26, 42, 16, 44, 8, package:zoo, 47, 9, 3, 50, 11, 14, 53, 12, 21, 56, 14, 58, 8, Goodbye, 61, 2, 41, 64, 11, 31, 67, 12, 69, 2, 2, 72, 6, 74, 11, 14, 77, 12, 21, 80, 13, 26]
完整示例
import 'dart:isolate';
import 'package:object_serializer/object_serializer.dart';
import 'package:object_serializer/serialize.dart';
import 'package:test/test.dart';
import 'package:tuple/tuple.dart';
Future<void> main() async {
test(
'Example',
() async {
final _ComplexType map = {
Uri.parse('package:animals'): [
Tuple2(BigInt.parse('1'), Tuple2(1, A('Hello'))),
Tuple2(BigInt.parse('2'), Tuple2(1, A('Hello'))),
],
Uri.parse('package:zoo'): [
Tuple2(BigInt.parse('1'), Tuple2(1, B('Goodbye', 41))),
Tuple2(BigInt.parse('2'), Tuple2(2, null)),
Tuple2(BigInt.parse('1'), Tuple2(1, A('Hello'))),
],
};
final stream = serializeMap(map, _collection);
//
final port = ReceivePort();
final isolate =
await Isolate.spawn<List>(compute, [port.sendPort, stream]);
final stream2 = await port.first as List;
isolate.kill(priority: Isolate.immediate);
//
final _ComplexType result = deserializeMap(stream2, _collection);
expect(result, map);
},
);
}
final _collection = ObjectSerializerCollection()
..addSerializer(ListSerializer<Tuple2<BigInt, Tuple2<int, Base?>>>())
..addSerializer(_ASerializer())
..addSerializer(_BSerializer())
..addSerializer(_BigIntSerializer())
..addSerializer(_Tuple2Serializer<BigInt, Tuple2<int, Base?>>())
..addSerializer(_Tuple2Serializer<int, Base?>())
..addSerializer(_UriSerializer());
void compute(List args) {
final sendPort = args[0] as SendPort;
final input = args[1] as List;
final _ComplexType map = deserializeMap(input, _collection);
final output = serializeMap(map, _collection);
sendPort.send(output);
}
typedef _ComplexType = Map<Uri, List<Tuple2<BigInt, Tuple2<int, Base?>>>>;
class A extends Base {
A(super.base);
@override
bool operator ==(other) => other is A && other.base == base;
}
class B extends Base {
final int x;
B(super.base, this.x);
@override
bool operator ==(other) => other is B && other.base == base && other.x == x;
}
class Base {
final String base;
Base(this.base);
}
class _ASerializer extends ObjectSerializer<A> {
@override
A deserialize(Deserializer deserializer) {
return A(
deserializer.readObject(),
);
}
@override
void serialize(Serializer serializer, A object) {
serializer.writeObject(object.base);
}
}
class _BigIntSerializer extends ObjectSerializer<BigInt> {
@override
BigInt deserialize(Deserializer deserializer) {
return BigInt.parse(deserializer.readObject());
}
@override
void serialize(Serializer serializer, BigInt object) {
serializer.writeObject('$object');
}
}
class _BSerializer extends ObjectSerializer<B> {
@override
B deserialize(Deserializer deserializer) {
return B(
deserializer.readObject(),
deserializer.readObject(),
);
}
@override
void serialize(Serializer serializer, B object) {
serializer.writeObject(object.base);
serializer.writeObject(object.x);
}
}
class _Tuple2Serializer<T1, T2> extends ObjectSerializer<Tuple2<T1, T2>> {
@override
Tuple2<T1, T2> deserialize(Deserializer deserializer) {
return Tuple2(
deserializer.readObject(),
deserializer.readObject(),
);
}
@override
void serialize(Serializer serializer, Tuple2<T1, T2> object) {
serializer.writeObject(object.item1);
serializer.writeObject(object.item2);
}
}
class _UriSerializer extends ObjectSerializer<Uri> {
@override
Uri deserialize(Deserializer deserializer) {
return Uri.parse(deserializer.readObject());
}
@override
void serialize(Serializer serializer, Uri object) {
serializer.writeObject(object.toString());
}
}
对于更简单或非通用的数据,需要更少的序列化器。但无论如何,每种数据都需要自己的序列化器。
这使得任何类型的数据都可以被序列化。例如,您可以序列化已解析的 AST。主要目标是使编写序列化器以在 isolat 之间传递数据变得更加容易。