Flutter开发技巧:Json转Model官方json_serializable

3,482 阅读3分钟

背景: 在开发中,服务端通常返回Json数据,我们需要将Json数据转模型对象来使用。一般情况下,我们会使用一些第三方库来动态转化Model,但是Flutter中没有像Java的Gson/Jackson这类Json序列化类库,因为Flutter中禁用运行时反射。官方解释是运行时反射会干扰Dart的tree shaking,使用tree shaking可以在release版中去除未使用的代码,这可以显著优化应用程序的大小。由于反射会默认应用到所有代码,因此tree shaking会很难工作,因为在启用反射时很难知道哪些代码未被使用,因此冗余代码很难剥离,所以Flutter中禁用了Dart的反射功能,而正因如此也就无法实现动态转化Model的功能。

json_serializable是dart官方推荐和提供的JSON转Model的方式:

  • 一个自动化源代码生成器来为你生成 JSON 序列化数据模板;
  • 由于序列化数据代码不再需要手动编写或者维护,你可以将序列化 JSON 数据在运行时的异常风险降到最低;

第1步:添加相关的依赖

依赖分为项目依赖(dependencies),开发依赖(dev_dependencies),在pubspec.yaml中添加如下依赖:

image.png

可以参考github官方案例中的配置,最新版本可以去库(点击搜索)中查找

  • 注意:添加后需要执行flutter pub get确保我们的项目中有这些依赖。
  • 注意:yaml配置文件对于缩进要求十分严格,下面的build_runnerjson_serializable应该是与flutter_test平级的,千万不要写在flutter_test缩进(空格)后,这样它会认为这两个是flutter_test的子集目录

第2步:新建 model 类,参考json_serializable 6.1.5

//1.import导入json_annotation.dart
import 'package:json_annotation/json_annotation.dart';
// 2.user.g.dart 将在我们运行生成命令后json_serializable帮我们自动生成.g.dart文件,在未执行命令前该行可能会报错
part 'example.g.dart';

//3.这个标注是告诉生成器,这个类是需要生成Model类的
@JsonSerializable()
class Person {
  /// The generated code assumes these values exist in JSON.
 
   //显式关联JSON字段名与Model属性的对应关系,
  // 如下将属性firstName和first_name字段关联
  @JsonKey(name: "first_name")
  final String firstName;
  final String lastName;
  
  /// The generated code below handles if the corresponding JSON value doesn't
  /// exist or is empty.
  final DateTime? dateOfBirth;

  //4.必须的构造方法
  Person({required this.firstName, required this.lastName, this.dateOfBirth});

  /// Connect the generated [_$PersonFromJson] function to the `fromJson`
  /// factory.
  //5.必须有的对应工厂构造器
  factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);

  /// Connect the generated [_$PersonToJson] function to the `toJson` method.
  //6.这里的tostring方法不是必须的,只是用来测试数据
  Map<String, dynamic> toJson() => _$PersonToJson(this);
}

第3步:通过指令生成example.g.dart文件

part of 'example.dart';

//它接收了一个map:Map<String, dynamic>,并将这个Map里的值映射为我们所需要的实体类对象。
//我们就可以使用这个方法,将存有json数据的map转化为我们需要的实体类对象。
Person _$PersonFromJson(Map<String, dynamic> json) => Person(
      firstName: json['firstName'] as String,
      lastName: json['lastName'] as String,
      dateOfBirth: json['dateOfBirth'] == null
          ? null
          : DateTime.parse(json['dateOfBirth'] as String),
    );
//将调用此方法的对象直接根据字段映射成Map。
//而这两个都是私有方法,part让两个文件共享作用域与命名空间,所以我们需要将生成的方法暴露给外部。
Map<String, dynamic> _$PersonToJson(Person instance) => <String, dynamic>{
      'firstName': instance.firstName,
      'lastName': instance.lastName,
      'dateOfBirth': instance.dateOfBirth?.toIso8601String(),
    };
指令

一次性生成指令

在项目终端运行下面的指令:

flutter  pub run build_runner build
  • 该指令是一次性生成JSON序列化的代码。 该指令通过我们的源文件,找出需要生成Model类的源文件(包含@JsonSerializable标注的)来生成对应的.g.dart文件。建议将所有Model类放在一个单独的目录下,然后在该目录下执行命令。

持续性生成指令

如果感觉每次更改Model时都需要执行一次性生成指令比较繁琐,这时可以使用下面的持续生成指令:

flutter pub run build_runner watch

在项目根目录下运行该指令后会启动观察器, 观察器可以监视我们项目中文件的变化,并在需要时自动构建必要的文件。只需启动一次观察器,然后它就会在后台运行,这种方式也很安全。

其他(json 转换成 model)

在线生成

image.png

JsonToDart 插件【推荐

  • 在 Android Studio中安装 JsonToDart 插件,打开 Preferences(Mac)或者 Setting(Window),选择 Plugins,搜索 JsonToDart

image.png 点击 Install(上图已经安装),安装完成后重启即可,如果搜索不到可以到官网下载本地安装。

官网 plugins.jetbrains.com/plugin/1256…

把生成好的文件下载下来贴到项目中,报错先不要管,进行g.dart生成,步骤回看指令生成