![](/img/trans.png)
[英]What's the best way to jSON serialize a .NET DataTable in WCF?
[英]What is the best way to serialize/deserialize Dart's new enum with JSON?
我想利用 Dart 的新(实验性) enum
功能而不是使用静态 const 字符串堆栈,但是使用 JSON 序列化/反序列化enum
变量的最佳方法是什么? 我已经使它以这种方式工作,但肯定有更好的解决方案:
enum Status {
none,
running,
stopped,
paused
}
Status status1 = Status.stopped;
Status status2 = Status.none;
String json = JSON.encode(status1.index);
print(json); // prints 2
int index = JSON.decode(json);
status2 = Status.values[index];
print(status2); // prints Status.stopped
如果您使用索引进行序列化,您可能会被锁定为永远保持枚举的顺序相同,所以我更喜欢使用某种字符串形式。 有人想出这个吗?
作为先前建议的答案之一,如果您在客户端和服务器上共享相同的实现,那么序列化名称是我认为最好的方法,并且尊重SOLID 设计中的打开/关闭原则,说明:
“软件实体(类、模块、函数等)应该对扩展开放,对修改关闭”
如果您需要向 Enum 添加另一个成员,则使用索引而不是名称会弄乱代码的所有逻辑。 但是,使用该名称将允许扩展。
最重要的是,序列化枚举的名称,为了正确反序列化它,编写一个小函数,将枚举作为字符串给出,迭代枚举的所有成员并返回适当的成员。 如:
Status getStatusFromString(String statusAsString) {
for (Status element in Status.values) {
if (element.toString() == statusAsString) {
return element;
}
}
return null;
}
所以,要序列化:
Status status1 = Status.stopped;
String json = JSON.encode(status1.toString());
print(json) // prints {"Status.stopped"}
并反序列化:
String statusAsString = JSON.decode(json);
Status deserializedStatus = getStatusFromString(statusAsString);
print(deserializedStatus) // prints Status.stopped
这是迄今为止我发现的最好的方法。 希望这可以帮助 !
使用枚举的name
属性和byName
方法
下面是一个示例代码来展示如何使用它:
import 'dart:convert';
void main() {
Person raj = Person(name: 'Raj', favIcecream: Icecream.pista);
print(raj.toJson());
Person rajV2 = Person.fromJson(raj.toJson());
print(rajV2.toJson());
final isBothInstanceEqual = raj == rajV2;
print('> Both instancecs are equal is $isBothInstanceEqual');
}
enum Icecream {
vanilla,
pista,
strawberry,
}
class Person {
String name;
Icecream favIcecream;
Person({
required this.name,
required this.favIcecream,
});
Map<String, dynamic> toMap() {
return {
'name': name,
'favIcecream': favIcecream.name, // <- this is how you should save
};
}
factory Person.fromMap(Map<String, dynamic> map) {
return Person(
name: map['name'] ?? '',
favIcecream: Icecream.values.byName(map['favIcecream']), // <- back to enum
);
}
String toJson() => json.encode(toMap());
factory Person.fromJson(String source) => Person.fromMap(json.decode(source));
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is Person &&
other.name == name &&
other.favIcecream == favIcecream;
}
@override
int get hashCode => name.hashCode ^ favIcecream.hashCode;
}
如果您使用的是 Dart 2.15.0+ (Flutter 2.8.0+)
您可以使用添加到枚举的新name
属性。
要将其转换为 json 值,您会这样做
Status status1 = Status.stopped;
String jsonValue = status1.name;
print(jsonValue); // prints "stopped"
要将其转换回枚举,您会这样做
String jsonValue = "stopped";
Status deserializedStatus = Status.values.byName(jsonValue);
print(deserializedStatus); // prints "Status.stopped"
我建议使用名为 json_serializable 的谷歌 aswome 库(此链接)
如此处所述:使用 JsonValue 注释枚举值以指定要映射到目标枚举条目的编码值。 值可以是 String 或 int 类型。
enum StatusCode {
@JsonValue(200)
success,
@JsonValue('500')
weird,
}
你可以在模型课上试试。
...
YourModel.fromJson(Map<String,dynamic> json){
status = Status.values.elementAt(json['status']);
}
Map<String, dynamic> toJson(Status status){
final Map<String, dynamic> data = <String, dynamic>{};
data['status'] = status.index;
return data;
}
...
看看我的回答here
在您的情况下,您可以将enum Color
替换为您的enum Status
:
enum Status {
none("nn"), // You can also use numbers as you wish
running("rn"),
stopped("st"),
paused("pa");
final dynamic jsonValue;
const Status(this.jsonValue);
static Status fromValue(jsonValue) =>
Status.values.singleWhere((i) => jsonValue == i.jsonValue);
}
或者如果你想使用jsonize包,你可以这样做:
import 'package:jsonize/jsonize.dart';
enum Status with JsonizableEnum {
none("nn"),
running("rn"),
stopped("st"),
paused("pa");
@override
final dynamic jsonValue;
const Status(this.jsonValue);
}
void main() {
// Register your enum
Jsonize.registerEnum(Status.values);
Map<String, dynamic> myMap = {
"my_num": 1,
"my_str": "Hello!",
"my_status": Status.running,
};
var jsonRep = Jsonize.toJson(myMap);
var backToLife = Jsonize.fromJson(jsonRep);
print(backToLife);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.