Flutter数据序列化插件enough_serialization的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter数据序列化插件enough_serialization的使用

1. 安装

首先,在你的pubspec.yaml文件中添加enough_serialization依赖:

dependencies:
  enough_serialization: ^1.4.0

2. 使用方法

enough_serialization提供了两种序列化模式:

  1. 继承SerializableObject或实现Serializable:适用于需要完全控制和处理复杂情况的场景。你需要将字段值存储在一个动态映射(Map<String, dynamic>)中。
  2. 实现OnDemandSerializable:仅在需要时读取和写入字段值到/从动态映射中。这种方式适用于简单的情况,但对嵌套结构有局限性。

3. 示例代码

简单示例

当只有基本字段(如Stringintdoublebool)时,使用非常简单:

import 'package:enough_serialization/enough_serialization.dart';

class SimpleArticle extends SerializableObject {
  String? get name => attributes['name'];
  set name(String? value) => attributes['name'] = value;

  int? get price => attributes['price'];
  set price(int? value) => attributes['price'] = value;

  double? get popularity => attributes['popularity'];
  set popularity(double? value) => attributes['popularity'] = value;
}

void simpleExample() {
  print('simple example:');
  final article = SimpleArticle()
    ..name = 'Remote Control'
    ..price = 2499
    ..popularity = 0.1;
  final serializer = Serializer();
  final json = serializer.serialize(article);
  print('serialized article: $json');

  final inputJson =
      '{"name": "Remote Control", "price": 2499, "popularity": 0.1}';
  final deserializedArticle = SimpleArticle();
  serializer.deserialize(inputJson, deserializedArticle);
  print('name: ${deserializedArticle.name}');
  print('price: ${deserializedArticle.price}');
  print('popularity: ${deserializedArticle.popularity}');
}
枚举示例

枚举类型不能自动序列化或反序列化,需要注册一个转换函数:

enum ArticleArea { electronics, music }

class ArticleWithEnum extends SerializableObject {
  ArticleWithEnum() {
    transformers['area'] = (value) =>
        value is ArticleArea ? value.index : ArticleArea.values[value];
  }

  ArticleArea? get area => attributes['area'];
  set area(ArticleArea? value) => attributes['area'] = value;

  String? get name => attributes['name'];
  set name(String? value) => attributes['name'] = value;
}

void enumExample() {
  print('enum example:');
  final article = ArticleWithEnum()
    ..area = ArticleArea.electronics
    ..name = 'Remote Control';
  final serializer = Serializer();
  final json = serializer.serialize(article);
  print('serialized article: $json');

  final inputJson = '{"area": 0, "name": "Remote Control"}';
  final deserializedArticle = ArticleWithEnum();
  serializer.deserialize(inputJson, deserializedArticle);
  print('area: ${deserializedArticle.area}');
  print('name: ${deserializedArticle.name}');
}
嵌套对象和复杂列表

对于嵌套对象和复杂列表,需要在objectCreators中注册创建函数:

class Article extends SerializableObject {
  Article() {
    transformers['area'] = (value) =>
        value is ArticleArea ? value.index : ArticleArea.values[value];
  }

  ArticleArea? get area => attributes['area'];
  set area(ArticleArea? value) => attributes['area'] = value;

  String? get name => attributes['name'];
  set name(String? value) => attributes['name'] = value;

  int? get price => attributes['price'];
  set price(int? value) => attributes['price'] = value;
}

class ElectronicsArticle extends Article {
  ElectronicsArticle() {
    area = ArticleArea.electronics;
  }

  String? get recommendation => attributes['recommendation'];
  set recommendation(String? value) => attributes['recommendation'] = value;
}

class MusicArticle extends Article {
  MusicArticle() {
    area = ArticleArea.music;
    objectCreators['band'] = (map) => Band();
  }

  Band? get band => attributes['band'];
  set band(Band? value) => attributes['band'] = value;
}

class Band extends SerializableObject {
  String? get name => attributes['name'];
  set name(String? value) => attributes['name'] = value;

  int? get year => attributes['year'];
  set year(int? value) => attributes['year'] = value;

  Band({String? name, int? year}) {
    this.name = name;
    this.year = year;
  }
}

class Order extends SerializableObject {
  Order() {
    objectCreators['articles'] = (map) => <Article>[];
    objectCreators['articles.value'] = (map) {
      final int areaIndex = map!['area'];
      final area = ArticleArea.values[areaIndex];
      switch (area) {
        case ArticleArea.electronics:
          return ElectronicsArticle();
        case ArticleArea.music:
          return MusicArticle();
      }
      return Article();
    };
  }

  List<Article>? get articles => attributes['articles'];
  set articles(List<Article>? value) => attributes['articles'] = value;
}

void complexExample() {
  print('complex example:');
  final order = Order()
    ..articles = [
      ElectronicsArticle()
        ..name = 'CD Player'
        ..price = 3799
        ..recommendation = 'Consider our streaming option, too!',
      ElectronicsArticle()
        ..name = 'MC Tape Deck'
        ..price = 12399
        ..recommendation = 'Old school, like it!',
      MusicArticle()
        ..name = 'The white album'
        ..price = 1899
        ..band = Band(name: 'Beatles', year: 1962)
    ];
  final serializer = Serializer();
  final json = serializer.serialize(order);
  print('order: $json');

  final inputJson =
      '{"articles": [{"area": 0, "name": "CD Player", "price": 3799, "recommendation": "Consider our streaming option, too!"}, '
      '{"area": 0, "name": "MC Tape Deck", "price": 12399, "recommendation": "Old school, like it!"}, '
      '{"area": 1, "name": "The white album", "price": 1899, "band": {"name": "Beatles", "year": 1962}}]}';
  final deserializedOrder = Order();
  serializer.deserialize(inputJson, deserializedOrder);
  for (var i = 0; i < deserializedOrder.articles!.length; i++) {
    final article = deserializedOrder.articles![i];
    print('$i: area: ${article.area}');
    print('$i: name: ${article.name}');
    print('$i: price: ${article.price}');
    if (article is ElectronicsArticle) {
      print('$i: recommendation: ${article.recommendation}');
    } else if (article is MusicArticle) {
      print('$i: band-name: ${article.band!.name}');
      print('$i: band-year: ${article.band!.year}');
    }
  }
}
嵌套映射

对于嵌套映射,同样需要在objectCreators中注册创建函数,并为非字符串键提供转换函数:

class MappedArticle extends SerializableObject {
  MappedArticle() {
    objectCreators['news-by-year'] = (map) => <int, String>{};
    transformers['news-by-year.key'] =
        (value) => value is int ? value.toString() : int.parse(value);
  }

  String? get name => attributes['name'];
  set name(String? value) => attributes['name'] = value;

  Map<int, String>? get newsByYear => attributes['news-by-year'];
  set newsByYear(Map<int, String>? value) => attributes['news-by-year'] = value;
}

void mapExample() {
  print('map example:');
  final newsByYear = {
    2020: 'Corona, Corona, Corona...',
    2021: 'The end of a pandemia',
    2022: 'Climate change getting really serious'
  };
  final article = MappedArticle()
    ..name = 'My Article'
    ..newsByYear = newsByYear;
  final serializer = Serializer();
  final json = serializer.serialize(article);
  print('article with map: $json');

  final inputJson =
      '{"name": "My Article", "news-by-year": {"2020": "Corona, Corona, Corona...", "2021": "The end of a pandemic", "2022": "Climate change getting really serious"}}';
  final deserializedArticle = MappedArticle();
  serializer.deserialize(inputJson, deserializedArticle);
  print('deserialized article: ${article.name}');
  for (final key in article.newsByYear!.keys) {
    print('$key: ${article.newsByYear![key]}');
  }
}
按需序列化

如果你不想使用动态映射来存储字段值,可以实现OnDemandSerializable接口:

class OnDemandArticle implements OnDemandSerializable {
  String? name;
  Map<int, String>? newsByYear;

  String serialize() {
    final serializer = Serializer();
    final json = serializer.serializeOnDemand(
      this,
      transformers: {
        'news-by-year.key': (value) =>
            value is int ? value.toString() : int.parse(value),
      },
    );
    return json;
  }

  void deserialize(String json) {
    final serializer = Serializer();
    serializer.deserializeOnDemand(
      json,
      this,
      transformers: {
        'news-by-year.key': (value) =>
            value is int ? value.toString() : int.parse(value),
      },
      objectCreators: {
        'news-by-year': (map) => <int, String>{},
      },
    );
  }

  @override
  void write(Map<String, dynamic> attributes) {
    attributes['name'] = name;
    attributes['news-by-year'] = newsByYear;
  }

  @override
  void read(Map<String, dynamic> attributes) {
    name = attributes['name'];
    newsByYear = attributes['news-by-year'];
  }
}

void onDemandExample() {
  print('on demand example:');
  final newsByYear = {
    2020: 'Corona, Corona, Corona...',
    2021: 'The end of a pandemia',
    2022: 'Climate change getting really serious'
  };
  final article = OnDemandArticle()
    ..name = 'My Article'
    ..newsByYear = newsByYear;
  final json = article.serialize();
  print('on demand article: $json');

  final inputJson =
      '{"name": "My Article", "news-by-year": {"2020": "Corona, Corona, Corona...", "2021": "The end of a pandemic", "2022": "Climate change getting really serious"}}';
  final deserializedArticle = OnDemandArticle();
  deserializedArticle.deserialize(inputJson);
  print('deserialized article: ${article.name}');
  for (final key in article.newsByYear!.keys) {
    print('$key: ${article.newsByYear![key]}');
  }
}

4. 主函数

最后,将所有示例整合到main函数中:

void main() {
  simpleExample();
  print('');
  enumExample();
  print('');
  complexExample();
  print('');
  mapExample();
  print('');
  onDemandExample();
}

更多关于Flutter数据序列化插件enough_serialization的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据序列化插件enough_serialization的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用enough_serialization插件进行数据序列化的示例代码。enough_serialization是一个用于Flutter的数据序列化库,它允许你轻松地将Dart对象转换为JSON格式,以及从JSON格式反序列化回Dart对象。

步骤 1: 添加依赖

首先,你需要在pubspec.yaml文件中添加enough_serialization的依赖:

dependencies:
  flutter:
    sdk: flutter
  enough_serialization: ^最新版本号  # 请替换为实际的最新版本号

然后运行flutter pub get来安装依赖。

步骤 2: 定义数据模型

接下来,定义一个需要序列化的数据模型。你需要让这个类实现Serializable接口,并且使用@Serializable()注解。

import 'package:enough_serialization/enough_serialization.dart';

@Serializable()
class User {
  final String name;
  final int age;

  User({required this.name, required this.age});

  // 工厂构造函数用于反序列化
  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);

  // 方法用于序列化
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

注意:_$UserFromJson_$UserToJson是自动生成的方法,用于处理序列化和反序列化。

步骤 3: 生成序列化代码

在项目根目录下运行以下命令来生成序列化代码:

flutter pub run build_runner build

这将生成需要的序列化代码文件。

步骤 4: 使用序列化功能

现在你可以在你的Flutter应用中使用这些序列化功能了。

void main() {
  // 创建一个User对象
  User user = User(name: 'Alice', age: 30);

  // 将User对象序列化为JSON
  Map<String, dynamic> userJson = user.toJson();
  print('Serialized User: $userJson');

  // 从JSON反序列化为User对象
  User deserializedUser = User.fromJson(userJson);
  print('Deserialized User: ${deserializedUser.name}, Age: ${deserializedUser.age}');
}

完整示例

以下是完整的代码示例,包括所有步骤:

// pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  enough_serialization: ^最新版本号  # 请替换为实际的最新版本号
  build_runner: ^最新版本号  # build_runner是生成序列化代码的工具

// user_model.dart
import 'package:enough_serialization/enough_serialization.dart';

part 'user_model.g.dart';  // 自动生成的文件

@Serializable()
class User {
  final String name;
  final int age;

  User({required this.name, required this.age});

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);

  Map<String, dynamic> toJson() => _$UserToJson(this);
}

// main.dart
import 'package:flutter/material.dart';
import 'user_model.dart';

void main() {
  // 创建一个User对象
  User user = User(name: 'Alice', age: 30);

  // 将User对象序列化为JSON
  Map<String, dynamic> userJson = user.toJson();
  print('Serialized User: $userJson');

  // 从JSON反序列化为User对象
  User deserializedUser = User.fromJson(userJson);
  print('Deserialized User: ${deserializedUser.name}, Age: ${deserializedUser.age}');

  // Flutter应用入口(仅为示例,实际使用时需构建UI)
  runApp(MaterialApp(
    home: Scaffold(
      appBar: AppBar(title: Text('Flutter Serialization Demo')),
      body: Center(child: Text('Check console for serialization output')),
    ),
  ));
}

确保在项目根目录下运行flutter pub run build_runner build来生成序列化代码文件user_model.g.dart

以上就是在Flutter项目中使用enough_serialization进行数据序列化的完整示例。希望这对你有所帮助!

回到顶部