我想为
AvailableService
设置默认值。对于原语来说它足够简单。我将如何使用自定义对象来做到这一点
class Submenu extends Equatable {
@JsonKey(defaultValue: "")
final String name;
@JsonKey(defaultValue: new AvailableService(false,false,false,false))
final AvailableService availableService;
}
自定义对象:
AvailableService {
bool supportsDelivery;
bool supportsTableService;
bool supportsCollection;
bool supportsChat;
}
编译时错误是
Arguments of a constant creation must be constant expressions.
Try making the argument a valid constant, or use 'new' to call the constructor
一般来说,作为注解参数,你只能传递常量,因此你不能传递用 new 创建的对象,而只能传递 const 构造函数(你应该将所有的 AvailableService 字段定义为 Final,并定义一个 const 构造函数)。 然而,在 json_Serialized 中,defaultValue 目前有一些额外的限制:
@JsonKey(defaultValue: {"supportsDelivery" : false, "supportsTableService" : false, /* etc */})
),但即使这种可能性目前也仅适用于具有 Map 类型的字段的默认值,而不适用于具有自定义类型的字段(如可用服务)。在这种情况下,您不会收到错误,但永远不会使用 defaultValue(通过查看 .g.dart 文件中生成的代码,您可以理解原因)。对于此问题也有开放请求:#676 - 允许默认值编码为 JSON 和 #789 - 如何为嵌套 JSON 对象设置默认值?因此,在跟进上述请求之前,我找到的唯一解决方法是处理
fromJson()
工厂中的 defaultValue:
factory AvailableService.fromJson(Map<String, dynamic> json) =>
json != null
? _$AvailableServiceFromJson(json)
: AvailableService(false, false, false, false);
简而言之,
JsonKey.defaultValue
目前只支持文字——甚至不接受常量——并且只能用于原始类型字段(或List、Map、Set)的默认值。
从json_serialized 5开始,生成的fromJson使用构造函数的默认参数,所以你可以这样做
@JsonSerializable()
class Cart {
final List<int> items;
const Cart({
this.items = const [],
});
factory Cart.fromJson(Map<String, dynamic> json) => _$CartFromJson(json);
Map<String, dynamic> toJson() => _$CartToJson(this);
}
@JsonSerializable()
class User {
final Cart cart;
const User({
this.cart = const Cart(),
});
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
然后
Cart.fromJson({}).items
或User.fromJson({}).cart.items
会给你[]
对于那些想要使用常量来更优化地管理源代码的人。
因为如果标签不是“字面量”,则
json_serializable
处理程序将在将标签传递给 defaultValue
时尝试调用“常量”函数。
所以你需要做的是创建一个返回默认值的静态函数:
@JsonSerializable(explicitToJson: true)
class MetadataDto {
@JsonKey(name: "version_name")
final String versionName;
@JsonKey(name: "version_code")
final int versionCode;
const MetadataDto({
this.versionName = "1.0.0",
this.versionCode = 1,
});
static MetadataDto kDefault() => const MetadataDto();
}
在另一个实例中,将单例函数设置为
defaultValue
正如其名称一样(不带括号)。
@JsonSerializable(explicitToJson: true)
class ContentDto {
@JsonKey(name: "metadata", defaultValue: MetadataDto.kDefault)
final MetadataDto info;
const ContentDto({
required this.info,
});
}
运行后检查
.g.dart
(生成的文件)build_runner
:
ContentDto _$ContentDto FromJson(Map<String, dynamic> json) =>
ContentDto(
info: json['metadata'] == null
? MetadataDto.kDefault()
: MetadataDto.fromJson(json['metadata'] as Map<String, dynamic>),
);
就是这样。