我在C#上进行序列化方面的经验很好,在搜索和测试了一些Dart库之后,我感到通常并没有真正令人满意的答案。
- 我想知道Dart中JSON序列化/反序列化的当前状态是什么?
- 我们应该期待未来会有什么改进吗?
- 这最终会得到语言本身的支持吗?
- 目前最佳实践是什么?
我也希望任何阅读此内容的人都能发布任何新信息,即使帖子变旧。
我在C#上进行序列化方面的经验很好,在搜索和测试了一些Dart库之后,我感到通常并没有真正令人满意的答案。
我也希望任何阅读此内容的人都能发布任何新信息,即使帖子变旧。
目前,最好的选择可能是使用Smoke库。
它是Mirrors功能的一个子集,但具有基于Mirrors和基于Codegen的实现。它由PolymerDart团队编写,因此它是我们能够获得的“官方”最接近的东西。
在开发过程中,它将使用基于Mirrors的编码/解码;但是对于发布,您可以创建一个小型转换器来生成代码。
Seth Ladd创建了这里的代码示例,我稍微扩展了一下以支持子对象:
abstract class Serializable {
static fromJson(Type t, Map json) {
var typeMirror = reflectType(t);
T obj = typeMirror.newInstance(new Symbol(""), const[]).reflectee;
json.forEach((k, v) {
if (v is Map) {
var d = smoke.getDeclaration(t, smoke.nameToSymbol(k));
smoke.write(obj, smoke.nameToSymbol(k), Serializable.fromJson(d.type, v));
} else {
smoke.write(obj, smoke.nameToSymbol(k), v);
}
});
return obj;
}
Map toJson() {
var options = new smoke.QueryOptions(includeProperties: false);
var res = smoke.query(runtimeType, options);
var map = {};
res.forEach((r) => map[smoke.symbolToName(r.name)] = smoke.read(this, r.name));
return map;
}
}
目前,在Smoke中没有支持获取通用类型信息(例如支持List)的功能;然而,我在这里提出了一个问题:
https://code.google.com/p/dart/issues/detail?id=20584
在此问题得到解决之前,实现您想要的“好”实现并不是真正可行的;但我希望它很快就会被实现;因为进行基本的JSON序列化有点依赖于它!
Alan Knight也正在开发一个序列化包,但我发现它缺乏对将日期时间转换为字符串等简单事物的支持,并且解决方案似乎过于冗长,而这些都是非常基本的。
目前,在我的项目中,我选择使用代码生成我们的JSON序列化(以toMap和fromMap方法的形式),因为我们已经有了服务器端的C#版本。如果时间允许,我想整理这些代码并制作一个NuGet包(它支持嵌套对象、数组、排除属性等)。
@JsonSerializable
和 @JsonKey
来控制序列化。 在我的经验中,它似乎可以完美地处理继承等问题。当您构建项目时,它会自动生成序列化和反序列化函数。目前,您可以使用redstone_mapper将Dart对象和JSON之间进行转换。这个包是Redstone.dart框架的一个插件,但也可以在没有该框架的情况下使用。此外,还有其他选项可在Pub上获得。
没有“一刀切”的序列化解决方案。有关详细讨论,请参见https://groups.google.com/a/dartlang.org/forum/#!searchin/misc/serialization/misc/0pv-Uaq8FGI/5iMrzOrlUKwJ。
https://github.com/google/built_value.dart
使用built_value,您的模型类如下所示:abstract class Account implements Built<Account, AccountBuilder> {
static Serializer<Account> get serializer => _$accountSerializer;
int get id;
String get name;
BuiltMap<String, JsonObject> get keyValues;
factory Account([updates(AccountBuilder b)]) = _$Account;
Account._();
}
请注意,built_value不仅涉及序列化 -- 它还提供了operator==、hashCode、toString和一个builder类。