FlutterflutterFlutter

[Flutter] 08-Flutter中的Json转Model

2020-06-23  本文已影响0人  codeTao

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

在此基础上,接下来我们看下Flutter中还有哪几种Json转模型的方式:

一. 手动转化

在上篇[Flutter] 07-Flutter中反序列化Json已经通过6个示例分析过了, 这里不再讨论。

二. json_serializable

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

第1步:添加相关的依赖

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

dependencies:
  json_annotation:^3.0.1

dev_dependencies:
  json_serializable:^3.2.5
  build_runner:^1.8.0

由于很多朋友在这一步遇到了问题,这里贴出源码:

第2步:以json_serializable 的方式创建模型类

final jsonInfo = {
  "nickname": "coderTao",
  "age": 20,
  "courses": ["政治", "高数", "英语"],
  "register_date": "2018-2-22",
  "computer": {
    "brand": "MackBook",
    "price": 9999
  }
};
// 1.import 导入json_annotation.dart
import 'package:json_annotation/json_annotation.dart';
import 'computer_model.dart';

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

// 3.这个标注是告诉生成器,这个类是需要生成Model类的
@JsonSerializable()
class User {
  String name;
  int age;
  //显式关联JSON字段名与Model属性的对应关系,
  // 如下将属性registerDate和register_date字段关联
  @JsonKey(name: "register_date")
  String registerDate;
  List<String> courses;
  Computer computer;
  // 4.必须的构造方法
  User(this.name, this.age, this.registerDate, this.courses, this.computer);
  // 5.必须有的对应工厂构造器
  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);

  //这里 toString方法不是必须的, 只是用测试数据
  @override
  String toString() {
    return'User{name: $name, age: ${age}, registerDate: $registerDate, courses: $courses, computer: $computer}';
  }
}
// 1.import 导入json_annotation.dart
import 'package:json_annotation/json_annotation.dart';

// 2.computer.g.dart 将在我们运行生成命令后json_serializable帮我们自动生成.g.dart文件,在未执行命令前该行可能会报错
part 'computer.g.dart';

// 3.这个标注告诉json_serializable哪一个类需要进行转换生成Model类
@JsonSerializable()
class Computer {
  String brand;
  double price;
  //4.必须的构造方法
  Computer(this.brand, this.price);
  //5.必须有的对应工厂构造器
  factory Computer.fromJson(Map<String, dynamic> json) => _$ComputerFromJson(json);
  Map<String, dynamic> toJson() => _$ComputerToJson(this);
    
  //这里 toString方法不是必须的, 只是用测试数据
  @override
  String toString() {
    return'Computer{brand: $brand, price: $price}';
  }
}

最后总结一下以json_serializable 的方式创建模型类必须5步:

import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';

备注1:
第五步实际就是创建两个方法:

备注2:

备注3:
UserFromJson(json)ToJson()调用方法,在未执行生成对应的.g.dart文件指令前该行可能会报错。

part 'computer.g.dart';part 'user.g.dart'; ,在未执行生成对应的.g.dart文件指令前该行可能会报错。

备注4:
toString方法不是必须的,只用来打印输出进行测试。

第3步:生成对应的.g.dart文件指令

该操作有两种指令:一次性生成指令和 持续性生成指令。

一次性生成指令

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

flutter pub run build_runner build

持续性生成指令

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

flutter pub run build_runner watch

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

第4步:测试并打印

final jsonInfo = {
  "nickname": "coderTao",
  "age": 20,
  "courses": ["政治", "高数", "英语"],
  "register_date": "2018-2-22",
  "computer": {
    "brand": "MackBook",
    "price": 9999
  }
};

final user = User.fromJson(jsonInfo);
print(user);

三. 网页转换

app.quicktype.io 是一个将JSON转换成模型类的工具网站,目前来看支持大部分常用语言,并且灵活的可选项也非常多:

优点: 这种方式操作起来会比使用json_serializable操作起来更简便一些,并且带下划线字段会自动转换为驼峰命名的属性名。
缺点: 如果数据过于复杂的话,在生成的时候可能会少了某一个类,并且不能进行父类抽取。

四. 编辑器插件

目前Android Studio(或IntelliJ)有几个插件,可以将json文件转成Model类,但插件质量参差不齐,甚至还有一些有抄袭嫌疑,故笔者在此不做优先推荐,读者有兴趣可以自行了解。

Json转Model几种方式总结:

总体推荐使用后两种,可以大大提升开发效率,不用埋头去搞一些重复的序列化工作。

由于笔者水平有限,文中如果有错误的地方,或者有更好的方法,还望大神指出。
附上本文的所有 demo 下载链接,【GitHub】
如果你看完后觉得对你有所帮助,还望在 GitHub 上点个 star。赠人玫瑰,手有余香。

上一篇 下一篇

猜你喜欢

热点阅读