结合上一篇介绍[Flutter]Json和序列化数据,看浏览关注的人还是很多。这里出一篇详细介绍json_serializable的属性参数的解析说明。此文章根据目前最新版本json_serializable: ^6.9.0介绍 ,下面开始:
// json_serializable模型写法示意
import 'package:json_annotation/json_annotation.dart';
//当前文件名+.g.dart
part 'device_model.g.dart';
//添加注解
@JsonSerializable()
class DeviceTypeNetModel {
final num? deviceType;
final String? deviceTypeName;
//自定义一些属性的某些设置
@JsonKey(name: 'num')
final int? count;
//构造函数
DeviceTypeNetModel(this.deviceType, this.deviceTypeName, this.count);
//工厂构造函数fromJson(也可以不写,需要配置对应的设置)
factory DeviceTypeNetModel.fromJson(Map<String, dynamic> json) =>
_$DeviceTypeNetModelFromJson(json);
//转json (也可以不写,需要配置对应的设置)
Map<String, dynamic> toJson() => _$DeviceTypeNetModelToJson(this);
}
@JsonKey(defaultValue: 'Unknown')
final String name;
如果 JSON 数据中没有 name 字段,默认值 Unknown 会被使用。
@JsonKey(disallowNullValue: true)
final String name;
如果 name 字段为 null,在序列化时将抛出错误。
@JsonKey(fromJson: _fromJson, toJson: _toJson)
final DateTime timestamp;
static DateTime _fromJson(String timestamp) {
return DateTime.parse(timestamp);
}
static String _toJson(DateTime timestamp) {
return timestamp.toIso8601String();
}
这里,timestamp 字段会使用自定义的 fromJson 和 toJson 方法进行解析和序列化。
@JsonKey(name: 'full_name')
final String name;
在上面的示例中,name 字段会被序列化为 full_name,而不是默认的 name。
@JsonKey(includeFromJson: true,includeToJson: true)
final String temporaryData;
这里,temporaryData 字段将不会出现在生成的 JSON 中,并且也不会参与 fromJson 过程。
@JsonKey(includeIfNull: false)
final String? email;
如果 email 字段为 null,它将不会出现在生成的 JSON 中。
@JsonKey(readValue: NormalTool.transFromMill)
final String timeMill;
class NormalTool {
static String transFromMill(Map p0, String p1) {
return p0[p1].toString();
}
}
//注意这里转化基本类型可以,但是如果是DateTime类型会出现不属于基本类型的转化toJson会被定义为String,进而影响fromJson的转化。
例如上述的如果转化为DateTime,得到的.g.dart的转化内容如下:
DeviceTypeNetModel _$DeviceTypeNetModelFromJson(Map<String, dynamic> json) =>
DeviceTypeNetModel(
DateTime.parse(NormalTool.transFromMill(json, 'timeMill') as String),
);
Map<String, dynamic> _$DeviceTypeNetModelToJson(DeviceTypeNetModel instance) =>
<String, dynamic>{
'timeMill': instance.timeMill.toIso8601String(),
};
@JsonKey(required: true)
final String name;
这意味着,name 字段在 JSON 中是必须存在的,否则解析时会抛出异常。
@JsonKey(unknownEnumValue: Gender.other)
final Gender gender;
如果 JSON 中的 gender 字段值不是枚举中定义的 male、female,则默认使用 Gender.other。
@JsonSerializable(anyMap: true)
class User {
final String name;
User({required this.name});
}
@JsonSerializable(checked: true)
class User {
final String name;
User({required this.name});
}
@JsonSerializable(constructor: 'customConstructor')
class User {
final String name;
User.customConstructor({required this.name});
}
在这个例子中,User 类会使用 customConstructor 来生成实例。
@JsonSerializable(createFieldMap: true)
class DeviceTypeNetModel {
final num? deviceType;
final String? deviceTypeName;
@JsonKey(name: 'num')
final int? count;
final DeviceListCountNetModel model;
DeviceTypeNetModel(this.deviceType, this.deviceTypeName, this.count, this.model);
Map<String, String> fieldMap() => _$DeviceTypeNetModelFieldMap;
}
.g.dart 会多一个内部私有方法
const _$DeviceTypeNetModelFieldMap = <String, String>{
'deviceType': 'deviceType',
'deviceTypeName': 'deviceTypeName',
'count': 'num',
'model': 'model',
};
@JsonSerializable(createJsonKeys: true)
class DeviceTypeNetModel {
final num? deviceType;
final String? deviceTypeName;
@JsonKey(name: 'num')
final int? count;
final DeviceListCountNetModel model;
DeviceTypeNetModel(this.deviceType, this.deviceTypeName, this.count, this.model);
}
.g.dart 会多一个内部私有方法
abstract final class _$DeviceTypeNetModelJsonKeys {
static const String deviceType = 'deviceType';
static const String deviceTypeName = 'deviceTypeName';
static const String count = 'num';
static const String model = 'model';
}
@JsonSerializable(createFactory: false)
class User {
final String name;
User({required this.name});
// 手动定义 fromJson 方法
static User fromJson(Map<String, dynamic> json) {
return User(name: json['name']);
}
}
@JsonSerializable(createToJson: false)
class User {
final String name;
User({required this.name});
// 手动定义 toJson 方法
Map<String, dynamic> toJson() {
return {'name': name};
}
@JsonSerializable(explicitToJson: true)
class User {
final String name;
final Address address;
User({required this.name, required this.address});
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
@JsonSerializable()
class Address {
final String city;
final String street;
Address({required this.city, required this.street});
factory Address.fromJson(Map<String, dynamic> json) => _$AddressFromJson(json);
Map<String, dynamic> toJson() => _$AddressToJson(this);
}
在这个例子中,User 类会显式调用 Address 类的 toJson,而不依赖于 json_serializable 的递归自动处理。
@JsonSerializable(fieldRename: FieldRename.snake)
class User {
final String firstName;
final String lastName;
User({required this.firstName, required this.lastName});
}
在这个例子中,firstName 会被转换为 first_name,lastName 会被转换为 last_name。
@JsonSerializable(ignoreUnannotated: true)
class User {
final String name;
@JsonKey(name: 'age_in_years')
final int age;
User({required this.name, required this.age});
}
如果你设置了 ignoreUnannotated: true,name 字段不会被包含在生成的 toJson 和 fromJson 方法中,只有 age 字段会被序列化。
@JsonSerializable(converters: [MyJsonConverter()])
class Example {
//也可以单独指定某一个属性做特殊自定义解释
//@MyJsonConverter()
final DateTime property;
Example(this.property);
}
class MyJsonConverter extends JsonConverter<DateTime, String> {
const MyJsonConverter();
@override
DateTime fromJson(String json) {
return DateTime.parse(json);
}
@override
String toJson(DateTime object) {
return '';
}
}
@JsonSerializable(createPerFieldToJson: true)
class DeviceTypeNetModel {
final num? deviceType;
final String? deviceTypeName;
@JsonKey(name: 'num')
final int? count;
final DeviceListCountNetModel model;
DeviceTypeNetModel(this.deviceType, this.deviceTypeName, this.count, this.model);
}
.g.dart 会多一个内部私有方法
// ignore: unused_element
abstract class _$DeviceTypeNetModelPerFieldToJson {
// ignore: unused_element
static Object? deviceType(num? instance) => instance;
// ignore: unused_element
static Object? deviceTypeName(String? instance) => instance;
// ignore: unused_element
static Object? count(int? instance) => instance;
// ignore: unused_element
static Object? model(DeviceListCountNetModel instance) => instance;
}
json serializable 在大概两年前发布的v3.5.0版本开始支持泛型,只需要在 @JsonSerializable() 注解中设置genericArgumentFactories为 true,同时需要对 fromJson 和 toJson 方法进行调整,即可支持泛型解析,如下所示:
@JsonSerializable(genericArgumentFactories: true)
class Response<T> {
int status;
T value;
factory Response.fromJson(Map<String, dynamic>json, T Function(dynamic json) fromJsonT) => _$ResponseFromJson<T>(json, fromJsonT);
Map<String, dynamic> toJson(Object? Function(T value) toJsonT) => _$ResponseToJson<T>(this, toJsonT);
}
得到的.g.dart 文件内容如下:
Response<T> _$ResponseFromJson<T>(
Map<String, dynamic> json,
T Function(Object? json) fromJsonT,
) =>
Response<T>(
(json['status'] as num).toInt(),
fromJsonT(json['value']),
);
Map<String, dynamic> _$ResponseToJson<T>(
Response<T> instance,
Object? Function(T value) toJsonT,
) =>
<String, dynamic>{
'status': instance.status,
'value': toJsonT(instance.value),
};
适用于一些固定结构,可以预处理一部分业务,其中某个参数根据业务变化在外部处理业务的场景(接口响应很经典)。
enum StatusCode {
@JsonValue(200)
success,
@JsonValue(301)
movedPermanently,
@JsonValue(302)
found,
@JsonValue(500)
internalServerError,
}
@JsonSerializable()
class BackModel {
StatusCode code;
BackModel(this.code);
factory BackModel.fromJson(Map<String, dynamic> json) =>
_$BackModelFromJson(json);
Map<String, dynamic> toJson() => _$BackModelToJson(this);
}
得到的.g.dart 文件内容如下:
BackModel _$BackModelFromJson(Map<String, dynamic> json) => BackModel(
$enumDecode(_$StatusCodeEnumMap, json['code'])
);
Map<String, dynamic> _$BackModelToJson(BackModel instance) => <String, dynamic>{
'code': _$StatusCodeEnumMap[instance.code]!,
};
const _$StatusCodeEnumMap = {
StatusCode.success: 200,
StatusCode.movedPermanently: 301,
StatusCode.found: 302,
StatusCode.internalServerError: 500,
};
或者
@JsonEnum(valueField: 'code')
enum StatusCodeEnhanced {
success(200),
movedPermanently(301),
found(302),
internalServerError(500);
const StatusCodeEnhanced(this.code);
final int code;
}
@JsonSerializable()
class BackModel {
StatusCodeEnhanced status;
BackModel(this.status);
factory BackModel.fromJson(Map<String, dynamic> json) =>
_$BackModelFromJson(json);
Map<String, dynamic> toJson() => _$BackModelToJson(this);
}
得到的.g.dart 文件内容如下:
BackModel _$BackModelFromJson(Map<String, dynamic> json) => BackModel(
$enumDecode(_$StatusCodeEnhancedEnumMap, json['status']),
);
Map<String, dynamic> _$BackModelToJson(BackModel instance) => <String, dynamic>{
'status': _$StatusCodeEnhancedEnumMap[instance.status]!,
};
const _$StatusCodeEnhancedEnumMap = {
StatusCodeEnhanced.success: 200,
StatusCodeEnhanced.movedPermanently: 301,
StatusCodeEnhanced.found: 302,
StatusCodeEnhanced.internalServerError: 500,
};
枚举记得使用注解unknownEnumValue,以便后续代码健壮性 @JsonKey(unknownEnumValue: Gender.other)
提示:请勿发布广告垃圾评论,否则封号处理!!