清单
- 您的类文件在 /lib 或 /bin 下
- 可以是那些下的子目录
- json_serializable 不会在每个目录中搜索要生成的文件。
- 为 json_annotation 添加了导入:
import 'package:json_annotation/json_annotation.dart';
- 您在
import 语句之后添加了一个part 指令
- 您的
part 文件以您的类文件名(不是类名本身)命名,并添加了g
- 例如对于
CacheItem 类...
-
cache-item.dart 类文件名 ...
-
part 'cache-item.g.dart'; 获取对应的part 指令。
-
part 指令不是以您的实际类命名的,而是类文件名。
- 您已在类名上方添加
@JsonSerializable()
- 您已经为您的类创建了一个默认构造函数。
- 它可以是空的、有可选的命名参数或位置参数。
- 只要您的类字段可访问(通过构造函数或公共 setter 和 getter),json_serializable 就可以处理它。 (即不只有 _private 属性和一个空的构造函数)
- 您编写了两个调用私有存根方法的方法:
- 工厂
fromJson方法
- 例如:
factory CacheItem.fromJson(Map<String,dynamic> json) => _CacheItemFromJson(json)
-
toJson 方法
- 例如:
Map<String,dynamic> toJson() => _$CacheItemToJson(this)
- 存根方法是私有的(以
_ 下划线开头)
- $tub 方法有
$
- 存根方法具有适当的 CaSe(即 Pascal Case)
- 存根
factory 提供 (Map<String,dynamic> json) 作为参数
- 存根
toJson()返回Map<String,dynamic>
所有这些都完成后,尝试从项目根目录中的命令行或终端运行生成器...
在颤振中:
flutter pub run build_runner build
在纯 Dart 中,这取决于您的版本,但其中之一应该可以工作:
dart run build_runner build
pub run build_runner build
dart pub run build_runner build
如果一切顺利,在您的项目文件资源管理器或Reload from disk 中单击,新文件应该会出现,例如上述示例中的cache-item.g.dart。
常见错误
Bad state: Unexpected diagnostics:
在运行 build_runner 时看到此输出可能是颤振和json_annotation 的问题,具体取决于analyzer 的不兼容版本。这发生在json_serializable 版本3.5 之前 需要dependency_override of analyzer 到 0.39.14 或 0.39.17。
您的第一步应该是尝试最新版本的json_serilizable from pub.dev apparently doesn't have this dependency problem。
如果您无法升级 json_serializable,您可以尝试将覆盖线放在 dev_dependences 下方:
dev_dependencies:
build_runner: ^1.9.0
flutter_test:
sdk: flutter
json_serializable: 3.3.0
test: ^1.14.3
dependency_overrides:
analyzer: '0.39.14'
[SEVERE] Nothing can be built, yet a build was requested.
当我们在 pubspec.yaml 中为 json_annotation 添加依赖项但缺少 json_serializable 的依赖项/dev_dependency 时,执行 flutter pub run build_runner build 时可能会发生此错误:
dependencies:
flutter:
sdk: flutter
get:
json_annotation: ^4.3.0
some_other_packages:
确保您已将 json_serializable 包添加为依赖项或 dev_dependency:
dependencies:
flutter:
sdk: flutter
get:
json_annotation: ^4.3.0
dev_dependencies:
build_runner: ^2.1.4
flutter_test:
sdk: flutter
json_serializable: ^6.0.1 #// ← do not forget
test:
Could not generate fromJsoncode forsomeField.
如果您要对包含 someField 的类进行 json 序列化,该类是您创建的另一个自定义类的类型,您有 @JsonSerializable() 那个其他自定义类吗?
@JsonSerializable(explicitToJson: true)
class BuildingStatus {
final Building building; // another custom class
BuildingStatus(Building building);
factory BuildingStatus.fromJson(Map<String,dynamic> json) => _$BuildingStatusFromJson(json);
Map<String,dynamic> toJson() => _$BuildingStatusToJson(this);
}
/// This guy needs serialization too.
@JsonSerializable()
class Building {
final String name;
const Building(this.name);
factory Building.fromJson(Map<String,dynamic> json) => _$BuildingFromJson(json);
Map<String,dynamic> toJson() => _$BuildingToJson(this);
}
如果不序列化嵌套的 Building 类,我们会在运行 build_runner 时看到如下错误:
Could not generate `fromJson` code for `building` because of type `Building`.
“SomeNestedClass”的实例
如果我们有嵌套的可序列化类,我们通常希望序列化以递归方式发生。即嵌套类也被序列化。
为此,我们将使用 explicitToJson: true 注释我们的包含类,例如:
@JsonSerializable(explicitToJson: true)
所以当我们toJson() 我们的BuildingStatus 实例时,而不是得到:
{"building": Instance of 'Building'}
...我们会得到:
{"building": {"name": "Empire State"}}
注意事项
子类/父类
如果您的类是父类的子类,并且您只想序列化子类的字段/属性,则可以仅注释子类。父类字段将自动找到并包含在为子类生成的类文件中。
如果您希望能够同时分别序列化/反序列化父类和子类,请继续使用@JsonSerializable 注释基类/父类。
例如文件名account.dart
import 'package:json_annotation/json_annotation.dart';
part 'account.g.dart';
class AccountBase {
int created;
String username;
String password;
}
@JsonSerializable()
class Account extends AccountBase {
int id;
Account();
factory Account.fromJson(Map<String,dynamic> json) => _$AccountFromJson(json);
Map<String,dynamic> toJson() => _$AccountToJson(this);
}
生产:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'account.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Account _$AccountFromJson(Map<String, dynamic> json) {
return Account()
..created = json['created'] as int
..username = json['username'] as String
..password = json['password'] as String
..id = json['id'] as int;
}
Map<String, dynamic> _$AccountToJson(Account instance) => <String, dynamic>{
'created': instance.created,
'username': instance.username,
'password': instance.password,
'id': instance.id,
};
参考和文档
示例
import 'package:json_annotation/json_annotation.dart';
part 'cache-item.g.dart';
@JsonSerializable()
class CacheItem {
int created;
String keywords;
String response;
CacheItem(this.created, this.keywords, this.response);
factory CacheItem.fromJson(Map<String,dynamic> json) => _$CacheItemFromJson(json);
Map<String,dynamic> toJson() => _$CacheItemToJson(this);
}
输出
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'cache-item.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
CacheItem _$CacheItemFromJson(Map<String, dynamic> json) {
return CacheItem(
json['created'] as int,
json['keywords'] as String,
json['response'] as String,
);
}
Map<String, dynamic> _$CacheItemToJson(CacheItem instance) => <String, dynamic>{
'created': instance.created,
'keywords': instance.keywords,
'response': instance.response,
};
示例构造函数变体
除了构造函数缺少一些字段并且response 是可选的之外,此示例与上面的示例相同。
没关系。
生成器将在实例化对象后仅使用公共(隐式)设置器来分配值。
import 'package:json_annotation/json_annotation.dart';
part 'cache-item.g.dart';
@JsonSerializable()
class CacheItem {
int created;
String keywords;
String response;
CacheItem({this.response});
factory CacheItem.fromJson(Map<String,dynamic> json) => _$CacheItemFromJson(json);
Map<String,dynamic> toJson() => _$CacheItemToJson(this);
}
输出
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'cache-item.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
CacheItem _$CacheItemFromJson(Map<String, dynamic> json) {
return CacheItem(
response: json['response'] as String,
)
..created = json['created'] as int
..keywords = json['keywords'] as String;
}
Map<String, dynamic> _$CacheItemToJson(CacheItem instance) => <String, dynamic>{
'created': instance.created,
'keywords': instance.keywords,
'response': instance.response,
};