我使用的是Flutter Freezed包,而它又使用Dart json_serialize包。
我有一个Dart增强枚举,包含2个字段:
enum WorkingMode {
mix(type: 1, name: "mix"),
parallel(type: 2, name: "parallel"),
sequential(type: 3, name: "sequential"),
relay(type: 4, name: "relay"),
free(type: 5, name: "free"),
associative(type: 6, name: "associative");
final int type;
final String name;
const WorkingMode({
required this.type,
required this.name,
});
}
字符串
在这个@freezed
类中引用的:
@freezed
class Test with _$Test {
const factory Test({
required List<WorkingMode> workingModes,
}) = _Test;
factory Test.fromJson(Map<String, Object?> json) => _$TestFromJson(json);
}
型
下面是fromJson()方法生成的代码:
_$_Test _$$_TestFromJson(Map<String, dynamic> json) => _$_Test(
workingModes: (json['workingModes'] as List<dynamic>)
.map((e) => $enumDecode(_$WorkingModeEnumMap, e))
.toList(),
);
const _$WorkingModeEnumMap = {
WorkingMode.mix: 'mix',
};
型
该代码期望仅基于一个特定字段(在本例中为name
字段)解码最终值。我的意思是,如果收到的JSON是这样的:
{
"workingModes":[
"parallel",
"sequential",
"mix",
"relay",
"free",
"associative"
]
}
型
但我遇到的问题是,我从Java REST API接收到的JSON以及枚举中的所有字段,如下所示:
{
"workingModes":[
{
"type":2,
"name":"parallel"
},
{
"type":3,
"name":"sequential"
},
{
"type":1,
"name":"mix"
},
{
"type":4,
"name":"relay"
},
{
"type":5,
"name":"free"
},
{
"type":6,
"name":"associative"
}
]
}
型
我尝试使用@JsonValue
和@JsonEnum(valueField: 'XXX )
注解,但似乎您可以指定另一个不同的字段,但不能同时指定几个字段。
现在我已经通过@JsonKey
编写自己的fromJson/toJson方法来解决这个问题:
@freezed
class Test with _$Test {
const factory Test({
@JsonKey(
fromJson: fromJsonWorkingModes,
toJson: toJsonWorkingModes,
)
required List<WorkingMode> workingModes,
}) = _Test;
factory Test.fromJson(Map<String, Object?> json) => _$TestFromJson(json);
}
List<WorkingMode> fromJsonWorkingModes(List<dynamic> rawWorkingModes) {
return rawWorkingModes
.map((rawWorkingMode) => WorkingMode.values
.firstWhere((element) => element.type == rawWorkingMode['type']))
.toList();
}
List<dynamic> toJsonWorkingModes(List<WorkingMode> workingModes) {
List<dynamic> finalWorkingModes = [];
for (WorkingMode workingMode in workingModes) {
var data = {'type': workingMode.type, 'name': workingMode.name};
finalWorkingModes.add(data);
}
return finalWorkingModes;
}
型
但我想知道这是否可以以更直接的形式进行。当然,另一种可能性是去掉增强的枚举,并将其转换成一个普通类,也用@freezed
注解,但这样我就失去了枚举的所有好处。
谢谢
2条答案
按热度按时间vshtjzan1#
目前我还不能对此进行测试,但似乎预期的方法是使用
JsonEnum
装饰器来指定要表示序列化枚举的字段。字符串
efzxgjgh2#
正如@Abion47所指出的,源问题是我没有从REST API点接收到严格的枚举对象。
这个问题至少有两种可能的解决方案。
第一个是通过
@JsonKey
使用带有自定义fromJson/toJson字段的枚举,如原始帖子中所述。另一种解决方案是使用密封类。我创建了密封类,如下所示。请注意,对于我的特定情况,使用
@Freezed(unionKey: 'name')
和@FreezedUnionValue
来适应JSON中接收到的名称。字符串
和反序列化JSON的基类如下:
型