当 Flutter 中的 JsonBean 遇到了泛型

前言

1
Flutter 中,带泛型的 Bean 通常来说会存在,处理起来似乎有些麻烦。

起因

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
28
import 'dart:convert';

import 'package:json_annotation/json_annotation.dart';

part 'json_bean.g.dart';

@JsonSerializable()
class JsonBean<T> {
final String name;
final T data;

JsonBean({
required this.name,
required this.data,
});

@override
List<Object?> get props => [name, data];

factory JsonBean.fromJson(Map<String, dynamic> json) => _$JsonBeanFromJson(json);

@override
Map<String, dynamic> toJson() => _$JsonBeanToJson(this);

@override
String toString() => json.encode(toJson());
}

  • 定义了一个 JavaBean,加了 @JsonSerializable() 注解,跑自动化脚本发现,竟然报错了:
  • 自动化脚本:flutter packages pub run build_runner build --delete-conflicting-outputs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[SEVERE] json_serializable:json_serializable on lib/model/business/json_bean.dart:

Could not generate `fromJson` code for `data` because of type `T` (type parameter).
To support type parameters (generic types) you can:
* Use `JsonConverter`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonConverter-class.html
* Use `JsonKey` fields `fromJson` and `toJson`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html
* Set `JsonSerializable.genericArgumentFactories` to `true`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/genericArgumentFactories.html
package:insight_bank/model/business/json_bean.dart:8:11

8 │ final T data;
│ ^^^^


  • 好家伙,从报错上看,定义了泛型,就没法生成 fromJson 方法了。
  • 好在,他给了我们推荐,即是将 genericArgumentFactories 设为 true
  • 于时,我们将类的注解改为了如下,并跑自动化脚本
1
2
3
4
5
6
7
8
9
10
import 'dart:convert';

import 'package:json_annotation/json_annotation.dart';

part 'json_bean.g.dart';

@JsonSerializable(genericArgumentFactories: true)
class JsonBean<T> {

}
  • 这次能成功跑脚本了,但跑完发现。fromJsontoJson 方法的参数个数对应不上。
  • 在原文件中,fromJsontoJson 只有一个参数,但生成的 json_bean.g.dart 竟然是两个参数。
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 'json_bean.dart';

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

JsonBean<T> _$JsonBeanFromJson<T>(
Map<String, dynamic> json,
T Function(Object? json) fromJsonT,
) =>
JsonBean<T>(
name: json['name'] as String,
data: fromJsonT(json['data']),
);

Map<String, dynamic> _$JsonBeanToJson<T>(
JsonBean<T> instance,
Object? Function(T value) toJsonT,
) =>
<String, dynamic>{
'name': instance.name,
'data': toJsonT(instance.data),
};

  • 什么意思呢,就是说,想使用泛型的 fromJsontoJson 方法,必须要自带解析器才行。
  • 这不就坑人么?泛型解析不了?
  • 原来,泛型因不知道解析后的 T 的类型,必须要我们传进支才行!
  • 于是,这个 JsonBean 改成了如下:
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
28
29
30
31
32
33
34
35
import 'dart:convert';

import 'package:json_annotation/json_annotation.dart';

part 'json_bean.g.dart';

@JsonSerializable(genericArgumentFactories: true)
class JsonBean<T> {
final String name;
final T data;

JsonBean({
required this.name,
required this.data,
});

@override
List<Object?> get props => [name, data];

factory JsonBean.fromJson(
Map<String, dynamic> json,
T Function(dynamic json) fromJsonT, // 新加参数
) =>
_$JsonBeanFromJson(json, fromJsonT);

@override
Map<String, dynamic> toJson(
Object? Function(T value) toJsonT, // 新加参数
) =>
_$JsonBeanToJson(this, toJsonT);

@override
String toString() => json.encode(toJson());
}

  • 但是,我们在使用的时候怎么处理呢? 最关键的是自定义处理器要怎么写?
  • 以下为一个参考:
1
2
3
// 没有指定 Model,需要根据具体的 Model,传递一个自定义的转换器进去进行转换
converter(json) => ShareModel.fromJson(json as Map<String, dynamic>);
final data = JsonBean<ShareModel>.fromJson(response.data!, converter);
  • 处理器实际上是一个参数,即泛型对应的类,类的 fromJsontoJson 方法。

后记

  • 这是本人在写某项通用配置需求时遇到的难点之一。
  • 由于对 Flutter 不太熟练,查看了大量的资料。

参考资料

https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/genericArgumentFactories.html



当 Flutter 中的 JsonBean 遇到了泛型
http://jxr202.github.io/flutter/flutter_008-97bfe4c9ae98/
作者
Jiang
发布于
2023年11月1日
许可协议