当前位置: 首页 > 面试题库 >

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

严宇
2023-03-14
问题内容

当谈到Dart中的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"
}

例如,ToJson在ServiceStack.Text中进行比较。

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

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

…仅产生具有值的数组(无键):

[17,"John"]

另一方面,使用默认的SimpleMapFormat会生成此复杂的表示形式。

仍然没有找到我想要的东西…

编辑2 :添加一些上下文:我正在Dart中构建一个RESTful
Web服务,并且我正在寻找一个JSON序列化,可以轻松地被任何客户端使用,而不仅仅是另一个Dart客户端。例如,向Stack Exchange
API查询此问题将创建此JSON响应。这是我正在寻找的序列化格式。-或者,查看Twitter
REST API或Facebook Graph
API返回的典型JSON响应。

编辑3 :我写了一个关于此的小博客文章。另请参阅关于“黑客新闻”
的讨论。


问题答案:

IMO这是Dart的主要缺点,考虑到其以Webhtml" target="_blank">应用程序为重点,这令人惊讶。我本以为在标准库中拥有JSON支持,这意味着将类与JSON进行序列化就像水一样工作,不幸的是JSON支持似乎不完整,在这里似乎选择使用松散类型的地图或遭受苦难通过不必要的样板配置您的标准(PODO)类以按预期进行序列化。

没有反射和镜像支持

由于流行的Dart平台(例如Flutter)不支持反射/镜像,因此您唯一的选择是使用代码生成解决方案。我们在ServiceStack
对Dart和Flutter的本机支持中采用的方法使您可以从远程URL为所有ServiceStack服务生成类型化的Dart模型,例如:

$ npm install -g @servicestack/cli

$ dart-ref https://www.techstacks.io

在.NET Core和任何.NET流行的托管选项中受支持。

上面的示例使用从www.techstacks.io/types/dart端点生成的DTO,为.NET
Core 2.0 TechStacks项目生成Typed API
。这将按照Dart的JsonCodec模式生成模型,您可以在其中通过提供命名的构造函数和实例方法为Dart模型自定义序列化,这是生成的DTO之一的示例:fromJson``toJson()

class UserInfo implements IConvertible
{
    String userName;
    String avatarUrl;
    int stacksCount;

    UserInfo({this.userName,this.avatarUrl,this.stacksCount});
    UserInfo.fromJson(Map<String, dynamic> json) { fromMap(json); }

    fromMap(Map<String, dynamic> json) {
        userName = json['userName'];
        avatarUrl = json['avatarUrl'];
        stacksCount = json['stacksCount'];
        return this;
    }

    Map<String, dynamic> toJson() => {
        'userName': userName,
        'avatarUrl': avatarUrl,
        'stacksCount': stacksCount
    };

    TypeContext context = _ctx;
}

使用此模型,您可以使用Dart内置的json:convert
API将模型序列化和反序列化为JSON,例如:

//Serialization
var dto = new UserInfo(userName:"foo",avatarUrl:profileUrl,stacksCount:10);
String jsonString = json.encode(dto);

//Deserialization
Map<String,dynamic> jsonObj = json.decode(jsonString);
var fromJson = new UserInfo.fromJson(jsonObj);

这种方法的好处是,它可以在 所有Dart平台上使用 ,包括Flutter和AngularDart或带有和不带有Dart 2的“强模式”的Dart
Web应用程序。

生成的DTO也可以与servicestack的Dart包一起使用,以启用端到端类型化解决方案,该解决方案需要将JSON序列化进出您的类型化DTO,例如:

var client = new JsonServiceClient("https://www.techstacks.io");
var response = await client.get(new GetUserInfo(userName:"mythz"));

有关更多信息,请参阅ServiceStack的本机Dart支持文档。

飞镖镜

如果您在可提供镜像支持的平台上使用Dart,那么我发现使用Mixin花费的精力最少,例如:

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"}

注意:[请参阅使用镜像的警告](https://www.dartlang.org/articles/reflection-with-

mirrors/)



 类似资料:
  • 我用的是Django 2。十、 我有一个用于验证请求的序列化程序。(不是ModelSerializer) 是对模型的引用。 我希望用户在字段中传递数据库id,但在验证后,got被转换为对象。 我试图重写方法,并将对象分配给字段,但它给出了错误

  • 问题内容: 我试图通过rest API将数据添加到数据库中,但是在添加数据时遇到一些问题。因此,基本上我已经从管理页面添加了此数据,但是我想通过使用请求从其他python添加此数据。当我发送发布请求时,它表明已添加该请求,但传感器数组为空 models.py serializers.py adddata.py payload2看起来像 问题答案: 我已经尝试过使用单站和多个传感器,但是我想您将能够

  • 它提供类实例信息,但不提供类实例的序列化内容。 我做错了什么?

  • 问题内容: 我已经搜索了很长时间,但没有成功。我的项目未使用Django,是否有一种简单的方法可以将App Engine模型(google.appengine.ext.db.Model)序列化为JSON,还是需要编写自己的序列化程序? 模型: 问题答案: 一个简单的递归函数可用于将一个实体(和任何引用对象)转换为可传递给的嵌套字典:

  • 若要添加一个新的表,点击工具栏的 “表”按钮,并点击画布的任意位置。你可以从浏览器的模型选项卡添加一个现有的表,简单地从模型选项卡拖放表到画布。 如果图表符号设置为默认, 图标代表字段为一个主键。而 图标则代表字段为一个索引。 【注意】如果你按住 Control 键并点按字段,你可以选择添加、插入、删除、重命名字段及设置字段为主键。 在画布中表对象的弹出式菜单选项包括: 选项 描述 设计表 在“表

  • 若要添加一个新的表,点击工具栏的 “表”按钮,并点击画布的任意位置。你可以从浏览器的模型选项卡添加一个现有的表,简单地从模型选项卡拖放表到画布。 如果图表符号设置为默认, 图标代表字段为一个主键。而 图标则代表字段为一个索引。 【注意】如果你右击字段,你可以选择添加、插入、删除、重命名字段及设置字段为主键。 在画布中表对象的弹出式菜单选项包括: 选项 描述 设计表 在“表设计器”中编辑表结构,例如