2016-03-22 9 views
2

Ich habe an einem RCP-Client gearbeitet, um Wetterdaten zu verarbeiten.Mein RCP-Client gibt keine tiefe Kopie eines Objekts zurück

Was ich mache, ist 2 Dinge, zuerst habe ich den JSON scrapped ich werde verwenden und es in eine Dart-Datei. Siehe: https://dartpad.dartlang.org/a9c1fe8ce34c608eaa28

Meine server.dart Seite werden die Wetterdaten importieren, und dann gehen Sie folgendermaßen vor:

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

So kann der Server korrekt gestartet wird, und ich werde gehen zu localhost:12345/test_server/v1/daily und es wird zurückkehren dieses:

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

das ist nicht korrekt. Wenn Sie die JSON-Daten nachschlagen, sind Zusammenfassung und Symbol beide Zeichenfolgen und Daten sind ein Array. Sie sind auch leer und sollten die Daten enthalten, die ich zurückgeben wollte.

Warum tritt dies auf? Ist es, weil ich eine Map<String, Object> zurückgebe? Ich habe versucht, es einzurichten: Map<String, dynamic>, aber der Dart-Compiler mochte es nicht.

Wie bekomme ich diese Daten, um den richtigen Datensatz zurückzugeben?

Die Dart-Website für RPC befindet sich unter: https://github.com/dart-lang/rpc und Sie können sehen, dass unter Methoden der Rückgabewert einer Methode entweder eine Instanz einer Klasse oder eine Zukunft sein kann. Das macht Sinn wie üblich, also setze ich es auf Map<String,Object>, obwohl ich versuche, vage zu sein, indem ich sage: Map war nicht ausreichend.

Edit:

Wenn dies meist ohne RPC in dart Pad tut, scheint es richtig zu arbeiten, die von einer Probe von: https://dartpad.dartlang.org/3f6dc5779617ed427b75

Dies führt mir etwas falsch mit dem Parsing-Tool zu glauben, Wie es scheint, ermöglicht der Rückgabetyp im Dartpad die Rückgabe von Map, Map<String, Object> und Map<String, dynamic>.

+0

Ich möchte einen Grund für den Downvote. Ich glaube, das ist eine gut durchdachte Frage mit einem soliden Codebeispiel. – Fallenreaper

+0

Mach dir keine Sorgen zu viel. Wenn jemand abwinkt, ohne einen Kommentar zu hinterlassen, was verbessert werden muss, ist es am besten, ihn zu ignorieren. Ich habe RPC nicht verwendet, weiß also nicht, worum es bei dem Problem geht. –

Antwort

1

einen kurzen Blick auf die RPC-Paket README hier hatte Nachdem https://pub.dartlang.org/packages/rpc, scheint es, dass Methoden wie Api Methoden markiert (mit @ApiMethod) sollte eine Instanz einer Klasse mit einfachen Feldern zurückkehren, wie:

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

Das RPC-Paket nimmt diese Instanz und serialisiert sie basierend auf den Feldnamen in JSON.

Aus der Readme:

Die MyResponse Klasse eine nicht-abstrakte Klasse mit einem ungenannten Konstruktor nimmt keine erforderlichen Parameter sein muss. Der RPC-Backend wird automatisch alle öffentlichen Bereiche des der Instanz MyResponse in JSON serialisiert ...

Sie eine verschachtelte MapDarstellung des JSON Rückkehr Sie die RPC-Operation wollen emittieren und würde vermuten, dass Das RPC-Paket wird nicht so behandelt, wie Sie es erwarten.

Re: diese aus Ihrer Frage:

Dies führt mir etwas falsch mit dem Parsing-Tool zu glauben, als es der Rückgabetyp in dartpad scheint erlaubt Karte, Karte, und Map zurückzukehren.

In Ihrem Beispiel gibt es kein 'Parsen' auf JSON. Die Daten, die Sie haben, sind eine Reihe von verschachtelten Literal Dart Map s, List s und String s mit der gleichen Struktur wie die JSON, die es abgeleitet wurde. Es sieht einfach wie JSON aus.

In Ihrem Beispiel sind Sie nur die Auswahl und das Drucken eines Unter Karte Ihrer Datenkarte (data['daily']), die die String ausdruckt, die den Aufruf von toString() führt - was rekursiv ist, so dass Sie die Inhalte aller verschachtelten Karten erhalten und Listen darin.

Es handelt sich also nicht um ein 'Deep Copy'-Problem, sondern um einen Unterschied in der Art und Weise, wie toString() und der RPC-Code eine Gruppe von verschachtelten Maps verarbeiten.

BTW: der Rückgabetyp Ihrer getDaily() Methode ist unerheblich. Was zurückgegeben wird, ist nur ein Map was auch immer der deklarierte Rückgabetyp der Methode ist. Denken Sie daran, dass Typen in Dart optional sind und dass Redakteure und Compiler potentiell falschen Code erkennen können. Siehe https://www.dartlang.org/docs/dart-up-and-running/ch02.html#variables.

+0

Wie würde ich das dann lösen? Das Ergebnis sortieren und dann auf dem Client analysieren? Das ist eine gültige Antwort, aber plausibel nicht die beste. Ihre Antwort ist sehr informativ, obwohl ich dies auf dem * RPC Github * gesehen habe. Nur die öffentlichen Felder der Klassen sind kodiert/decodiert.Derzeit unterstützte Typen für die öffentlichen Felder sind int, double, bool, String, DateTime, List, Map und eine weitere Nachrichtenklasse. – Fallenreaper

0

Ich werde Huckepack von @ Argenti Apparatus hier, da es eine Menge von Informationen von ihm gewonnen wurde.

Lange Rede kurzer Sinn, der erforderliche Rückgabetyp der Methode:

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

ist der Fehler.

Ich ging durch und aktualisierte die Methodensignatur zu Map<String,String> und es analysierte es vollständig korrekt. Es analysierte das Objekt nicht als Zeichenfolge, sondern analysierte es tatsächlich als vollständiges rekursives Objekt.

Ich ging durch und wegen der Sauberkeit des Codes auch Signaturen der Wettereigenschaften geändert, um zu reflektieren, was sie tatsächlich waren, Map<String,Object> sowie.

Alles in allem, wenn es als Werttyp von Object definiert wurde, gab es geschweifte Klammern zurück, aber als String wurde es richtig geparst.

Ich lief es durch JSLint, um zu bestätigen, dass es auch korrekt ist.

Ich gab +1 an den Helfer, ich musste tiefer in den Code graben, um zu sehen WARUM es war nicht eine Karte richtig.

Das finde ich auch, ist plausibel ein Bug in RPC Dart.

+0

Ich bin froh, Ihnen helfen zu können. Ich bin mir nicht sicher, ob dies ein Fehler im RPS-Paket per se ist, aber vielleicht fehlt es an Dokumentation darüber, wie es mit Karten umgeht. Übrigens könnten Sie Map als Typ für heterogene Maps verwenden. –

+0

Ich habe dich dazu geschlagen, ich habe 'Map ' ausprobiert und der Dart-Compiler hat ein Zischen über die dynamische Verwendung geworfen. – Fallenreaper

+0

Compiler? Das ist Server-Side-Code, oder? Was beklagt sich eigentlich darüber? Übrigens, kannst du meine Antwort als Antwort auf deine Frage akzeptieren, wenn du es fühlst - thx. –