gson 下划线转驼峰 注解_Flutter自动解析JSON数据(序列化/反序列化)

本文介绍了Flutter中使用json_serializable插件进行JSON序列化和反序列化的详细步骤,包括添加依赖、定义Model、执行命令生成解析代码。通过示例展示了如何处理下划线命名与驼峰命名不一致的情况,以及为何Flutter选择生成代码而非使用反射机制的原因。
摘要由CSDN通过智能技术生成

在客户端开发的过程中,JSON的序列化与反序列化是一个常见的操作,通常我们的API服务端会返回JSON格式的数据。此时我们就需要解析JSON并转化为客户端中的对象。在客户端开发的初期,我们需要人工解析每一个字段,类似于很多obj.id = json[‘id’],obj.name = json[‘name’]…这样的代码。

遥想当年笔者刚接触Android开发的时候,刚开始并没有使用Gson,Jackson等自动解析工具,所以就出现了全体成员编写解析JSON代码的壮观景象!

手动解析JSON的缺点是:一、效率低下,我们浪费了大量的时间在写一些枯燥无比的代码,这样简直就是浪费生命。二、容易出错,我们谁都不能保证我们在敲代码的过程中不会敲错一个字母,于是就会出现解析异常,程序崩溃等BUG。

在Flutter发布的初期,并没有一个成熟的方式解析JSON,好在目前我们有了’json_serializable‘这个插件。通过这个插件,我们可以生成所有序列化/反序列化的方法。本文我们就来介绍如何生成解析JSON的方法。

一、添加插件依赖

在我们Flutter工程的pubspec.yaml中添加如下:

1

2

3

4

5

6

7

8

9# 其他的依赖也添加到这里

dependencies:

analyzer: 0.38.2

json_annotation: ^3.0.0

# 这里是开发期间使用的插件

dev_dependencies:

build_runner: ^1.6.7

json_serializable: ^3.2.2

添加完后在工程根目录下执行’flutter pub get’,或者在Android Studio中点击’Packages get’按钮,下载插件。

注意这里指定版本的依赖’analyzer: 0.38.2’,加入这个是因为在json_annotation的最新3.x版本存在一些问题,会导致生成解析JSON错误,如果后续解决了这个问题,可以把这个依赖删除。

二、定义Model

下面我们定义一个Model,这里我们以User举例。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22import 'package:json_annotation/json_annotation.dart';

import 'package:x_marriage/core/models/region.dart';

part 'user.g.dart';

@JsonSerializable(explicitToJson: true)

class User{

int id;

String name;

Region address;

@JsonKey(name: 'login_time')

DateTime loginTime;

User();

factory User.fromJson(Map json) =>

_$UserFromJson(json);

Map toJson() => _$UserToJson(this);

}

定义完后,我们会发现AS会提示错误:

原因很简单,因为文件”user.g.dart”还有下面的方法我们还没有生成。不过不用担心,下面我们执行生成命令后,这些错误都会消失。

注意这里:

1@JsonSerializable(explicitToJson: true)

这个注解的意思是在我们User中有嵌套对象时,调用User的toJson()方法时,也会调用嵌套对象的toJson()方法。比如上面的User中的address。

还有一点我们需要注意:

1

2@JsonKey(name: 'login_time')

DateTime loginTime;

当API返回的字段与我们的字段不一致时,比如客户端使用驼峰的命名方式,服务器采用下划线的命名方式,我们就可以使用‘@JsonKey’来指定解析特定字段。

三、执行命令,生成解析代码

在工程的根目录下执行:

1flutter pub run build_runner build

执行后我们会看到日志信息:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27[INFO] Generating build script...

[INFO] Generating build script completed, took 481ms

[INFO] Initializing inputs

[INFO] Reading cached asset graph...

[INFO] Reading cached asset graph completed, took 140ms

[INFO] Checking for updates since last build...

[INFO] Checking for updates since last build completed, took 1.1s

[INFO] Running build...

[INFO] 1.1s elapsed, 0/16 actions completed.

[INFO] 2.3s elapsed, 0/16 actions completed.

[INFO] 3.4s elapsed, 0/16 actions completed.

[INFO] 4.5s elapsed, 0/16 actions completed.

[INFO] 10.4s elapsed, 1/16 actions completed.

[INFO] 11.6s elapsed, 3/18 actions completed.

[INFO] 12.8s elapsed, 17/29 actions completed.

[INFO] 13.8s elapsed, 53/65 actions completed.

[INFO] 15.0s elapsed, 65/79 actions completed.

[INFO] 16.0s elapsed, 87/97 actions completed.

[INFO] Running build completed, took 16.4s

[INFO] Caching finalized dependency graph...

[INFO] Caching finalized dependency graph completed, took 129ms

[INFO] Succeeded after 16.5s with 24 outputs (118 actions)

执行完后我们会发现工程中多了刚才User中缺少的文件:

在这个文件中,之前我们报错的方法’$UserFromJson’和 ‘$UserToJson’也都生成好了:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'user.dart';

// **************************************************************************

// JsonSerializableGenerator

// **************************************************************************

User _$UserFromJson(Map json) {

return User()

..id = json['id'] as int

..name = json['name'] as String

..address = json['address'] == null

? null

: Region.fromJson(json['address'] as Map)

..loginTime = json['login_time'] == null

? null

: DateTime.parse(json['login_time'] as String);

}

Map _$UserToJson(User instance) => {

'id': instance.id,

'name': instance.name,

'address': instance.address?.toJson(),

'login_time': instance.loginTime?.toIso8601String(),

};

这样解析JSON的代码就生成完毕了!Happy Coding!

其他一些问题的探讨

模板类

简单来说,生成自动解析JSON的代码就两步:一、定义Model。二、执行生成命令。非常简单。

但是我们发现定义Model时略显啰嗦。需要定义part …,和这两个方法’$UserFromJson’和 ‘$UserToJson’,相信没人喜欢每次都写这样的代码!笔者的做法是定义一个模板文件,每次需要新建Model类时就拷贝一下,改一下文件名和类名,然后只需要定义其属性即可。

代码也放上,如果有人喜欢,可以也定义这样一个类在工程中。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16import 'package:json_annotation/json_annotation.dart';

part 'template_model.g.dart';

@JsonSerializable(explicitToJson: true)

class TemplateModel{

String value;

TemplateModel();

factory TemplateModel.fromJson(Map json) =>

_$TemplateModelFromJson(json);

Map toJson() => _$TemplateModelToJson(this);

}

为什么需要生成代码?

比如其他的一些序列化/反序列化的库,比如Gson、Jackson等,我们不需要生成代码,直接可以进行解析,而在Flutter中,我们却需要用生成代码的方式,为什么呢?

因为Flutter禁用了Dart中的反射机制。上面的库中由于使用了反射机制,所以在运行时可以动态地解析Json字段并赋值。

为什么Flutter要禁用反射机制呢?因为在构建阶段Flutter可以知道哪些代码被使用了,哪些代码没有被使用,在构建时可以删除掉没用使用的代码,从而减小安装包的体积。如果使用了反射,则很难去发现那些未被使用的代码。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值