将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)