将JSON序列化器添加到每个模型类?

当谈到飞镖的JSON编码时,根据Seth Ladd的判断 ,现在最终批准的官方方式是使用dart:convert + JSON.Encode

假设我们有一堆模型类( PODO ),例如:

 class Customer { int Id; String Name; } 

现在,我希望能够像这样对域对象进行JSON编码:

 var customer = new Customer() ..Id = 17 ..Name = "John"; var json = JSON.encode(customer); 

不幸的是,这不会工作…

 Uncaught Error: Converting object to an encodable object failed. Stack Trace: #0 _JsonStringifier.stringifyValue (dart:convert/json.dart:416) #1 _JsonStringifier.stringify (dart:convert/json.dart:336) #2 JsonEncoder.convert (dart:convert/json.dart:177) .... 

…除非我们明确地告诉dart:convert如何编码:

 class Customer { int Id; String Name; Map toJson() { Map map = new Map(); map["Id"] = Id; map["Name"] = Name; return map; } } 

我真的必须添加一个toJson方法到每一个我的模型类,还是有更好的方法?

编辑 :这是我正在寻找的简单序列化:

 { "Id": 17, "Name": "John" } 

例如,比较ServiceStack.Text中的 ToJson

Dart的序列化库(参见下面的Matt B的答案)似乎是向正确的方向迈出的一步。 但是,这…

 var serialization = new Serialization() ..addRuleFor(Customer); var json = JSON.encode(serialization.write(customer, format: new SimpleJsonFormat())); 

…只产生一个数组(无键):

 [17,"John"] 

另一方面,使用默认的SimpleMapFormat生成这个复杂的表示。

还没find我要找的东西…

编辑2 :添加一些上下文:我在Dart构build一个REST风格的Web服务,我正在寻找一个JSON序列化,可以很容易地被任何客户端使用,而不仅仅是另一个Dart客户端。 例如,查询堆栈交换API这个问题将创build这个JSON响应 。 这是我正在寻找的序列化格式。 – 或者,查看Twitter REST API或Facebook Graph API返回的典型JSON响应。

编辑3 :我写了一个关于这个小博客文章 。 另见关于黑客新闻的讨论 。

国际海事组织这是飞镖的一个主要的短暂的未来,令人惊讶的考虑到其Web应用程序的重点 我以为在标准库中有JSON支持就意味着将JSON序列化和从JSON序列化就像水一样工作,不幸的是,JSON支持似乎不完整,似乎select使用松散types的地图或遭受通过不必要的样板来configuration您的标准(PODO)类以按预期序列化。

说了我发现使用Mixin需要最less的努力,例如:

 import 'dart:convert'; import 'dart:mirrors'; abstract class Serializable { Map toJson() { Map map = new Map(); InstanceMirror im = reflect(this); ClassMirror cm = im.type; var decls = cm.declarations.values.where((dm) => dm is VariableMirror); decls.forEach((dm) { var key = MirrorSystem.getName(dm.simpleName); var val = im.getField(dm.simpleName).reflectee; map[key] = val; }); return map; } } 

您可以将其与您的PODO课程混合在一起:

 class Customer extends Object with Serializable { int Id; String Name; } 

你现在可以使用JSON.encode

 var c = new Customer()..Id = 1..Name = "Foo"; print(JSON.encode(c)); 

结果:

 {"Id":1,"Name":"Foo"} 

注意: 请参阅使用镜像的注意事项

我写了可导出的库来解决像转换到地图或JSON这样的东西。 使用它,模型声明如下所示:

 import 'package:exportable/exportable.dart'; class Customer extends Object with Exportable { @export int id; @export String name; } 

如果你想转换成JSON,你可以:

 String jsonString = customer.toJson(); 

而且,从JSONstring初始化新对象也很容易:

 Customer customer = new Customer()..initFromJson(jsonString); 

或者:

 Customer customer = new Exportable(Customer, jsonString); 

请参阅自述文件以获取更多信息。

另一种方法是使用序列化包,并为您的类添加规则。 最基本的forms使用reflection来自动获取属性。

Redstone映射器是我用过的最好的序列化库。 JsonObject和Exportable的缺点是你不得不扩展他们的一些类。 与红石映射器,你可以有这样的结构

 class News { @Field() String title; @Field() String text; @Field() List<FileDb> images; @Field() String link; } 

它可以与getter和setter一起使用,你可以通过不用@Field()注释来隐藏信息,你可以将字段从/重命名为json,嵌套对象,它可以在服务器和客户端上运行。 它还与红石服务器框架集成在一起,它有助手编码/解码到MongoDB。

我唯一看到的正确方向是Dartson ,但是与Redstone Mapper相比,它仍然缺less一些特性。

我已经解决了:

 class Customer extends JsonObject { int Id; String Name; Address Addr; } class Address extends JsonObject{ String city; String State; String Street; } 

但我的目标是绑定数据从/到JSON从/到模型类; 如果您可以修改模型类,则此解决scheme可以工作,相比之下,您必须使用解决scheme“external”来转换模型类;

另请参阅: 使用Dart中的JsonObject库parsingJSON列表

解决这个问题的另一个软件包是built_value:

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不只是序列化 – 它还提供了运算符==,hashCode,toString和一个构build器类。

我用dartson ,感觉非常简单和熟悉(如果你来自Java)