这确实不是我推荐的解决方案,但我最终这样做主要是为了“好玩”。除了它很可怕之外,我不保证解决方案的任何内容。 :)
问题是enum 没有被定义为 Json 的有效类型,所以整个概念确实给我们带来了一些问题。一种解决方案是将enum 值转换为String,首先使用枚举的名称,然后是值的名称,例如MyFirstEnum.first1。如果在 enum 值上调用 toString(),Dart 会给出这种表示形式。
这很好,但为了安全起见,我们还可以在开头添加一个魔术字符串,如 DART_ENUM:MyFirstEnum.first1,这样更容易在其他字符串之间识别,这些字符串可能与 enum 值同名而不是枚举。
接下来是类型安全。在 Json 中,我们知道所有的地图都有String 作为键的类型。通过制作我们自己的enum 表示并允许它也是键,我们不能期望解码器返回例如Map<String, dynamic> 但必须返回 Map<dynamic, dynamic>。
话虽如此,我尝试构建一个处理enum 值的Json 解码器和编码器。它也适用于地图中的enum 键:
import 'dart:convert';
class JsonConverterWithEnumSupport {
final String magicString;
final Set<Object> allEnumValues = {};
final Map<String, Object> enumStringToEnumValue = {};
JsonConverterWithEnumSupport(List<List<Object>>? enumsValues,
{this.magicString = "DART_ENUM:"}) {
enumsValues?.forEach(addEnumValues);
}
void addEnumValues(List<Object> enumValues) {
for (final enumValue in enumValues) {
enumStringToEnumValue[enumValue.toString()] = enumValue;
allEnumValues.add(enumValue);
}
}
String _addMagic(dynamic enumValue) => '$magicString$enumValue';
String _removeMagic(String string) => string.substring(magicString.length);
String encode(Object? value) =>
json.encode(value, toEncodable: (dynamic object) {
if (object is Map) {
return object.map<dynamic, dynamic>((dynamic key, dynamic value) =>
MapEntry<dynamic, dynamic>(
allEnumValues.contains(key) ? _addMagic(key) : key,
allEnumValues.contains(value) ? _addMagic(value) : value));
}
if (object is List) {
return object.map<dynamic>(
(dynamic e) => allEnumValues.contains(e) ? _addMagic(e) : e);
}
if (allEnumValues.contains(object)) {
return _addMagic(object);
}
return object;
});
dynamic decode(String source) => json.decode(source, reviver: (key, value) {
if (value is String && value.startsWith(magicString)) {
return enumStringToEnumValue[_removeMagic(value)];
}
if (value is Map) {
return value.map<dynamic, dynamic>((dynamic key, dynamic value) =>
MapEntry<dynamic, dynamic>(
(key is String) && key.startsWith(magicString)
? enumStringToEnumValue[_removeMagic(key)]
: key,
value));
}
return value;
});
}
enum MyFirstEnum { first1, first2 }
enum MySecondEnum { second1, second2 }
void main() {
final converter =
JsonConverterWithEnumSupport([MyFirstEnum.values, MySecondEnum.values]);
final jsonString = converter.encode({
MyFirstEnum.first1: [MySecondEnum.second2, MySecondEnum.second1],
'test': {MyFirstEnum.first2: 5}
});
print(jsonString);
// {"DART_ENUM:MyFirstEnum.first1":["DART_ENUM:MySecondEnum.second2","DART_ENUM:MySecondEnum.second1"],"test":{"DART_ENUM:MyFirstEnum.first2":5}}
print(converter.decode(jsonString));
// {MyFirstEnum.first1: [MySecondEnum.second2, MySecondEnum.second1], test: {MyFirstEnum.first2: 5}}
}
您需要将所有可能的enum 值输入JsonConverterWithEnumSupport(例如,请参阅底部的main 方法)。
如果您不想在每个 enum 上附加魔术字符串,您可以创建 JsonConverterWithEnumSupport 并使用:magicString: '' 作为参数。