敞开成长之旅!这是我参加「日新计划 12 月更文应战」的第1天,点击检查活动详情

背景

现在咱们项目中,解析 JSON 现已悉数运用官方推荐的 json_serializable 方案,为了协助团队熟悉 json_serializable,之前现已写过两篇相关文章:

Flutter 运用 json_serializable 解析 JSON 支撑泛型

Flutter 运用 json_serializable 解析 JSON 时支撑枚举 Enum 类型

而且咱们还开发了一款 Android Studio/IDEA 插件 FlutterJsonToDart,协助咱们开发过程中生成 Model 类:

Flutter 运用 json_serializable 解析 JSON 最佳方案

以上文章根本能够处理咱们大部分需求,不过在遇到一些特殊需求时,仍是要检查官方文档。在检查官方文档时,如果不是自己动手实践一下,有时仍是很难了解各个类或者字段的意思。

这篇文章主要是我参照 json_serializable 官方文档,并结合一些测验,做的一些记录,方便后续查阅,发布出来,也希望能够协助到我们。

json_serializable 库供给的有 5 个注解类 JsonSerializable JsonKey JsonValue JsonLiteral JsonEnum,下面分别介绍一下这几个类和他们的特点

JsonSerializable

nullable

现已抛弃了,即使赋值了,也会被疏忽

anyMap

Flutter json_serializable 解析 JSON 使用详解

默许值为 false,如果设置为 true,生成的 _$HelloFromJson() 办法中的 json 是 Map 类型,如果不设置或者为 false ,是 Map<String,dynamic> 类型

这个参数一般状况下咱们运用不到,如果没有特殊状况,不要运用,官方文档说他会添加代码巨细

checked

Flutter json_serializable 解析 JSON 使用详解

默许值为 false,如果设置为 true,会对参数进行类型检测,比方 model 界说的类型是 int,服务端回来 String,解析时,发现类型不一致,就会报 CheckedFromJsonException 异常

这个参数感觉也不常用,由于有时会存在相同字段名,服务端在不同状态回来不同类型的状况,这时一般需求咱们运用 JsonKey.fromJson 进行自界说解析

constructor

Flutter json_serializable 解析 JSON 使用详解

Flutter json_serializable 解析 JSON 使用详解

默许值为 “”,如果设置了值,_$HelloFromJson 会运用该值对应的命名结构办法

运用场景:

咱们能够经过装备 constructor: ‘_’

把结构办法修改为私有结构办法,避免外部调用

当 createFactory 为 false 时,由于不会生成 _$HelloFromJson 办法了,那么 constructor 装备会变得没有意义

createFactory

默以为 true,如果为 false ,就不会生成 _$HelloFromJson 办法。

createToJson 参数是用来操控是否生成 _$HelloToJson(this) 办法的。

没有想到这个参数有什么运用场景

createFieldMap

Flutter json_serializable 解析 JSON 使用详解
默以为 false,如果为 true, 会把所有的特点值生成一个 map,是为了方便其它代码生成工具运用的,比方 fieldRename.

createPerFieldToJson

默许值为 false, 如果设置为 true,会生成一个抽象类,并为每个特点生成一个静态办法。

暂时不清楚有什么用处

createToJson

默以为 true,如果设置为 false,就不生成 _$ExampleToJson(this) 办法了。

在咱们项目中,咱们发现 toJson 办法只要几种状况会运用到,大部分 model 类没有必要生成 toJson 办法,咱们采用的做法是在大局装备文件 build.yaml 中把这个默许值修改为 false。

如果某个 model 类需求生成 toJson 办法,那么再独自装备 @JsonSerializable(createToJson: true)

disallowUnrecognizedKeys

默以为 false,是否制止无法识别的 key,如果为 true,遇到了新的 key,会报 UnrecognizedKeysException 异常,

不主张装备这个特点

explicitToJson

Flutter json_serializable 解析 JSON 使用详解

默以为 false,这个特点是指生成 toJson 办法时,是否调用嵌套的子目标的 toJson 办法

explicitToJson 为 false,生成的数据为:

{name: 张三, type: 0, status: 0, child: Instance of \'Child\'}

explicitToJson 为 true,生成的数据为:

{name: 张三, type: 0, status: 0, child: {name: 你好}}

toJson 办法运用场景,1、向原生传值;2、数据本地持久化,涉及到这些场景时,需求设置 explicitToJson 为 true

fieldRename

默许 FieldRename.none,能够对 model 中的字段进行重命名

有以下几个值:

  • none:服务端回来的是啥,就用啥

  • kebab:把中划线 json key,重命名为驼峰,比方 kebab-case 会命名为 kebabCase

  • snake:把下划线 json key,重命名为驼峰,比方 snake_case 会命名为 snakeCase

  • pascal:把首字母大写的 json key 重命名为驼峰,比方 PascalCase 会重命名为 pascalCase

  • screamingSnake:把大写的带下划线的 json key 重命名为驼峰,比方 SCREAMING_SNAKE_CASE 会被重命名为 screamingSnakeCase

JsonKey.name 也能够修改字段称号,优先级 JsonKey.name 大于 fieldRename

如果后端接口比较规范,能够在 build.yaml 文件中进行大局装备,这样就不需求每个类,或者每个字段进行独自装备了

genericArgumentFactories

默以为 false,如果为 true, 敞开泛型支撑,详细运用参阅这篇文章

Flutter 运用 json_serializable 解析 JSON 支撑泛型

ignoreUnannotated

默以为 false,如果为 true,只要运用 JsonKey 注释的字段,才会生成代码,

和 JsonKey.includeToJson 和 JsonKey.includeFromJson 一样,

感觉没有运用场景

includeIfNull

Flutter json_serializable 解析 JSON 使用详解

默以为 true,生成 toJson 时是否过滤掉值为 null 的字段

优先级小于 JsonKey.includeIfNull

Hello hello = Hello(name: ‘张三’, type: null, status: null);

如果 includeIfNull 为 true,toJson 生成的数据为

{name: 张三, type: null, status: null}

如果 includeIfNull 为 false,toJson 生成的数据为

{name: 张三}

converters

默许 []

设置一个 JsonConverter 集合,JsonConverter 是用来自界说解析逻辑的,它是一个抽象类,有 fromJson 和 toJson 两个办法,和 JsonKey.fromJson 和 JsonKey.toJson 一样,都是为了完成自界说解析逻辑的,它的好处是能够简化代码,方便复用

JsonKey

nullable

现已抛弃了,即使赋值了,也会被疏忽

defaultValue

默许值,如果 json 中没有 model 界说字段对应的 key,或者对应 key的 值为 null,这时会运用默许值,这个特点比较常用

在咱们项目中,根本悉数的字段设置了默许值,

  • Int 类型一般默许设置为 0
  • String 类型一般默许值设置为 ”
  • List 类型一般默许设置为 []
  • Map 类型一般默许值设置为 {}
  • 目标类型,默许值现在还没有找到好的办法,暂时采用的办法是:在 ExampleModel 中建一个叫做 defaultValue 的命名结构办法,然后设置默许值时运用 ExampleModel.defaultValue,示例如下:
@JsonKey(defaultValue:ExampleModel.defaultValue) final ExampleModel example;

其它类型,默许值示例:

@JsonSerializable()
class Hello {
  @JsonKey(defaultValue: '')
  final String name;
  @JsonKey(defaultValue: 0)
  final int type;
  @JsonKey(defaultValue: 0)
  final int status;
  Hello({
    required this.name,
    required this.type,
    required this.status,
  });
  factory Hello.fromJson(Map<String, dynamic> json) => _$HelloFromJson(json);
  Map<String, dynamic> toJson() => _$HelloToJson(this);
}
test('hello json 1', () {
  String json = """
  {
    "name": null,
    "type": null
  }
  """;
  Hello hello = Hello.fromJson(jsonDecode(json));
  expect(hello.name, '');
  expect(hello.type, 0);
  expect(hello.status, 0);
});

能够看到,json 中 name 和 type 的值都为 null,经过 JsonSerializable 解析后,name 运用了设置的默许值 ”,type 运用了设置的默许值 0,json 中没有 status 这个 key,model 也运用了设置的默许值 0

disallowNullValue

默许 false, 如果为 true,制止 json 中 key 的值为 null ,当一个 key 的值为 null 时,解析时会报 DisallowedNullValueException 异常,

这个特点不常用

fromJson

fromJson 是一个函数,用来自己完成某个字段的解析逻辑

比方:有时一个 key 在不同状况下,有不同类型的值,比方

[
  {"id":1},
  {"id":"2"}
]

比方这个 id,可能是 int,也可能是 String,这时就能够经过 fromJson 函数来进行自界说解析

ignore

默许 false,如果为 true, 解析时会疏忽设置了这个特点的字段,一般应用于本地添加的字段。

比方:一个标签接口,回来了 id 和 name,咱们要完成标签选中效果,就在 model 中添加了一个 selected 字段,这个字段不用参加序列化,就能够运用 ignore: true 进行疏忽

includeIfNull

和 JsonSerializable.includeIfNull 一样,但是优先级大于它。 disallowNullValue 和 includeIfNull 是互斥的,如果一同设置为 true,代码生成时会报错,这个特点不常用

name

model 中字段对应 json 中的 key 的姓名,不设置时,字段是什么姓名,就到 json 中取对应姓名 key 的值。

readValue

这是一个函数,感觉和 fromJson 类似,看 issue ,是为了处理多个 JSON 字段映射到一个model 字段的

required

默许 false,如果为 true, 会检测 json 中是否存在对应的 key(即使该 key 的值是 nulll 也是合法的),没有的话,会报 MissingRequiredKeysException 异常。

toJson

toJson 是一个函数,用来自己完成某个字段的生成 json 的逻辑,和 fromJson 类似

unknownEnumValue

枚举类型的字段专用,当呈现了一个不知道的枚举值时,该如何处理

能够检查这篇文章:Flutter 运用 json_serializable 解析 JSON 时支撑枚举 Enum 类型

JsonEnum 和 JsonValue

JsonEnum 和 JsonValue 都是枚举专用注解,详细运用请参阅这篇文章:

Flutter 运用 json_serializable 解析 JSON 时支撑枚举 Enum 类型

JsonLiteral

能够把 一个 json 文件生成一个 Map 常量

@JsonLiteral('data.json')
Map get glossaryData => _$glossaryDataJsonLiteral;

测验这个特点的时分,发现 json 文件的途径只能是相对源码的相对途径

这个注解,现在不知道有什么运用场景,我能想到的运用场景可能是单元测验?

总结

这篇文章主要是参阅官方文档,并结合我自己做的一些测验,主要对 JsonSerializable 和 JsonKey 中的各个特点,依照我个人的了解,做的一个解说,可能会有了解错误的当地,如果我们发现了,欢迎指出,让咱们一同前进。