前言

背景

最近正在学习 flutter,准备手头的公司项目用 flutter 实现。但是碰到一个很现实的问题,就是 dart 的强类型特征。强类型自然有其好处,但是也有其弊端,就是定义实在是太麻烦了,我只写了一个类,因为这个类有 30 多个字段,然后我先写类的成员属性,再写构造函数,再写命名构造函数,就几乎崩溃了。然后发现还有一个要把实例序列化,好保存在 SQLite 里的需求,又多出一个只是转当前成员属性类型的方法,快把我弄崩溃了。

环境

  • Dart:2.7.1;
  • build_runner:1.8.0;
  • json_serializable:3.2.5;

目标

不需要手写序列化和反序列化的方法。

解决方案

后来在 flutter 官网上发现是有这样的解决方案的。就是这个解决方案写的不是很详细,很多操作细节都是分散的,因此在此记录一下。

安装相关依赖

pubspec.yaml 文件中加入两个依赖声明。

dev_dependencies:
  build_runner: ^1.8.0
  json_serializable: ^3.2.5

然后手动安装。友情提示:最好修改成国内源。

$ pub get # dart
$ flutter pub get # flutter

创建要序列化和反序列化的类文件

我们先创建一个 dog.dart 类文件。

import 'package:json_annotation/json_annotation.dart';

// 编辑器可能会提示错误,暂时不用管
part 'dog.g.dart';

@JsonSerializable(nullable: false)
class Dog {
  final int id;
  final String name;
  final int age;

  Dog({this.id, this.name, this.age});
}

使用命令行工具生成序列化和反序列化代码

这步一开始是最让我困惑的,不知道例子中的 *.g.dart 文件怎么来的,一开始还以为是手写的。查了一些资料以后才知道是靠命令行工具生成的。

$ pub run build_runner build # dart
$ flutter pub run build_runner build # flutter

运行成功后,就会发现自动生成了一个 dog.g.dart 文件。

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'dog.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

Dog _$DogFromJson(Map<String, dynamic> json) {
  return Dog(
    id: json['id'] as int,
    name: json['name'] as String,
    age: json['age'] as int,
  );
}

Map<String, dynamic> _$DogToJson(Dog instance) => <String, dynamic>{
  'id': instance.id,
  'name': instance.name,
  'age': instance.age,
};

修改要序列化和反序列化的类文件

import 'package:json_annotation/json_annotation.dart';

part 'dog.g.dart';

@JsonSerializable(nullable: false)
class Dog {
  final int id;
  final String name;
  final int age;

  Dog({this.id, this.name, this.age});

  // 增加序列化方法
  Map<String, dynamic> toMap() => _$DogToJson(this);
  
  // 增加反序列化方法
  factory Dog.fromJson(Map<String, dynamic> json) => _$DogFromJson(json);
}

然后就可以正常使用啦!

参考资料