我的 RCP 客户端没有返回对象的深层副本

My RCP Client is not returning a deep copy of an object

我一直在开发 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,它会 return 这个:

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

这是不正确的。查JSON数据,summary和icon都是字符串,data是数组。它们也是空的,应该包含我想要 return.

的数据

为什么会出现这种情况?是因为我 return 正在 Map<String, Object> 吗?我试图将其设置为:Map<String, dynamic> 但飞镖编译器不喜欢它。

如何将此数据获取到 return 正确的数据集?

RPC 的 Dart 网站位于:https://github.com/dart-lang/rpc 并且您可以看到在方法下,方法的 return 值可以是 class 的实例或未来。这和往常一样是有道理的,所以我将它设置为 Map<String,Object>,尽管试图含糊其辞地说:Map 是不够的。

编辑:

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

这让我相信解析工具有问题,因为 dartpad 中的 return 类型似乎允许 return MapMap<String, Object>Map<String, dynamic>.

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

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

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

来自自述文件:

The MyResponse class must be a non-abstract class with an unnamed constructor taking no required parameters. The RPC backend will automatically serialize all public fields of the the MyResponse instance into JSON ...

您正在 return 嵌套 Map 表示 您希望 RPC 操作发出的 JSON 并猜测RPC 包没有像您期望的那样处理它。

回复:这是你的问题:

This leads me to believe something is wrong with the Parsing tool as it seems the return type in dartpad allows to return Map, Map, and Map.

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

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

所以这不是 'deep copy' 问题,而是 toString() 和 RPC 代码处理一组嵌套映射的方式不同。

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

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

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

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

是错误。

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

为了代码整洁起见,我也修改了天气属性的签名以反映它们的实际情况,Map<String,Object>

总而言之,定义为Object的值类型时,return是大括号,但设置为String时解析正确。

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

我给助手 +1,我不得不深入研究代码以了解为什么它没有正确地执行地图。

我也觉得这可能是 RPC Dart 中的一个错误。