【问题标题】:My RCP Client is not returning a deep copy of an object我的 RCP 客户端未返回对象的深层副本
【发布时间】:2016-07-09 20:24:16
【问题描述】:

我一直在开发一个 RCP 客户端来处理天气数据。

我做的是两件事,首先我抓取了我将使用的 JSON 并将其放入一个 dart 文件中。见:https://dartpad.dartlang.org/a9c1fe8ce34c608eaa28

我的server.dart页面,会导入天气数据,然后进行如下操作:

import "dart:io";
import "weather_data.dart";
import "dart:convert";
import "package:rpc/rpc.dart";

find ApiServer _apiServer = new ApiServer(prettyPrint:true);
main() async {
  Weather w = new Weather(WeatherJson);
  TestServer ts = new TestServer(w);
  _apiServer.addApi(ts);
  HttpServer server = await HttperServer.bind(InternetAddress.ANY_IP_V4, 12345);
  server.listen(_apiServer.httpRequestHandler);
}

class Weather{
  Map weather;
  Weather(this.weather){
    Map get daily => weather["daily"];
  }
}

@ApiClass(name:"test_server", version: 'v1', description: 'This is a test server api to ping for some quick sample data.')
class TestServer {
  Weather myWeather;
  TestServer(this.myWeather){

  }

  @ApiMethod(method:'GET', path: 'daily')
  Map<String, Object> getDaily(){
    return myWeather.daily;
  }
}

所以,服务器正确启动,我会去localhost:12345/test_server/v1/daily,它会返回这个:

{
 "summary": {},
 "icon": {},
 "data": {}
}

这是不正确的。如果查找 JSON 数据,摘要和图标都是字符串,数据是数组。它们也是空的,应该包含我想要返回的数据。

为什么会发生这种情况?是因为我要返回Map&lt;String, Object&gt; 吗?我试图将其设置为:Map&lt;String, dynamic&gt; 但 dart 编译器不喜欢它。

如何让这些数据返回正确的数据集?

用于 RPC 的 Dart 网站位于:https://github.com/dart-lang/rpc 可以看到在methods下,方法的返回值可以是类的实例,也可以是future。按照惯例,这是有道理的,所以我将其设置为 Map&lt;String,Object&gt;,尽管试图含糊其辞地说:Map 是不够的。

编辑:

当主要在没有 RPC 的飞镖垫中执行此操作时,它似乎可以正常工作,通过以下示例:https://dartpad.dartlang.org/3f6dc5779617ed427b75

这让我相信解析工具有问题,因为似乎 dartpad 中的返回类型允许返回 MapMap&lt;String, Object&gt;Map&lt;String, dynamic&gt;

【问题讨论】:

  • 想要一个拒绝投票的理由。我相信这是一个经过深思熟虑的问题,有一个可靠的代码示例。
  • 别太担心。如果有人在没有发表评论的情况下投票否决了需要改进的地方,最好忽略它。我没有使用过 RPC,所以不知道是什么问题。

标签: json dart rpc


【解决方案1】:

我将在这里捎带@Argenti Apparatus,因为从他那里获得了很多信息。

长话短说,方法所需的返回类型:

@ApiMethod(method:'GET', path: 'daily')
Map<String,Object> getDaily(){       // <-- Map<String,Object>
  return myWeather.daily;
}

是错误。

我检查并更新了方法签名为Map&lt;String,String&gt;,它解析它完全正确。它并没有将对象解析为字符串,而是将其实际解析为完整的递归对象。

为了代码的整洁,我也更改了 Weather 属性的签名以反映它们的实际情况,Map&lt;String,Object&gt; 也是如此。

总而言之,当将其定义为 Object 的值类型时,它返回了花括号,但将其设置为 String 可以正确解析它。

我通过 JSLint 运行它以确认它也是正确的。

我给了帮助者一个 +1,我必须更深入地研究代码才能看到 为什么它没有正确地做地图。

我也觉得这似乎是 RPC Dart 中的一个错误。

【讨论】:

  • 很高兴为您提供帮助。我不确定这是 RPS 包本身的一个错误,但可能缺乏关于它如何处理地图的文档。顺便说一句,您可能会考虑使用 Map 作为异构地图的类型。
  • 我打败了你,我试过 Map&lt;String, dynamic&gt; 并且 Dart 编译器对使用的动态抛出了一个嘶嘶声。
  • 编译器?这是服务器端代码,对吧?究竟是在抱怨什么?顺便说一句,如果你觉得可以,你能接受我的回答作为回答你的问题吗?谢谢。
  • 服务器端代码,但是当它运行时,它会解析它并且不喜欢返回签名。您的回答在某种程度上是正确的,但没有明确指出错误。只要用户理解这两个帖子,我不确定我应该给你还是我。
【解决方案2】:

快速浏览了https://pub.dartlang.org/packages/rpc 此处的 RPC 包 README,似乎标记为 Api 方法(使用 @ApiMethod)的方法应该返回一个具有简单字段的类的实例,例如:

class ResourceMessage {
  int id;
  String name;
  int capacity;
}

RPC 包将采用该实例并根据字段名称将其序列化为 JSON。

来自自述文件:

MyResponse 类必须是具有未命名的非抽象类 构造函数不带任何必需参数。 RPC 后端将 自动序列化 MyResponse 的所有公共字段 实例化为 JSON ...

您正在返回您希望 RPC 操作发出的 JSON 的嵌套 Map表示,并且会猜测 RPC 包没有按照您的预期处理它。

回复:这是您的问题:

这让我相信解析工具有问题,因为 似乎 dartpad 中的返回类型允许返回 Map、Map 和 Map。

您的示例中没有对 JSON 进行“解析”。您拥有的数据是一组嵌套文字 Dart Maps、Lists 和 Strings,其结构与其派生的 JSON 相同。它恰好看起来像 JSON。

在您的示例中,您只是选择并打印数据映射 (data['daily']) 的子映射,它会打印出调用 toString() 产生的 String - 这是递归的,因此您可以获得里面的所有嵌套地图和列表。

所以这不是“深拷贝”问题,而是toString() 和 RPC 代码处理一组嵌套映射的方式不同。

顺便说一句:getDaily() 方法的返回类型无关紧要。无论方法声明的返回类型是什么,返回的只是Map。请记住,Dart 中的类型是可选的,编辑器和编译器可以在那里发现可能不正确的代码。见https://www.dartlang.org/docs/dart-up-and-running/ch02.html#variables

【讨论】:

  • 那我该如何解决这个问题呢?将结果字符串化然后在客户端解析它?这是一个有效的答案,但似乎不是最好的。您的回答非常有用,尽管我确实在 RPC Github Only the public fields of the classes are encoded/decoded. Currently supported types for the public fields are int, double, bool, String, DateTime, List, Map, and another message class. 上看到了这个
猜你喜欢
  • 2019-04-08
  • 2011-07-23
  • 2016-02-15
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
  • 2015-01-10
相关资源
最近更新 更多