2013-11-20 7 views
5

Mit go1.1.2 Win64 habe ich ein Go-Programm, das eine Struktur marshale, die ein float64 enthält. Wenn der Wert von float64 keine ganze Zahl ist, z. 1234.44, dann wird es "marshal" ed als float (json.Marshal). Wenn es jedoch eine ganze Zahl ist, z. "1234.00" wird es als Ganzzahl "1234" gemarshallt. Wenn ich das am anderen Ende (Dart) erhalte, behandelt Dart (30188) die ganze Zahl als Integer (in map - JSON.decode). Folglich bricht das Dart-Programm ab, wenn die Darstellung der float (double) -Daten keinen Dezimalpunkt enthält, und ich versuche, es aus der Karte als Doppel zu extrahieren.Funktioniert Go Float64 korrekt zu JSON?

Dies kann offensichtlich eine Reihe von verschiedenen Möglichkeiten gelöst werden (z. B. konvertieren in Integer und dann zurück in Float konvertieren), aber ich fragte mich, ob es einen anderen (besseren) Weg, um mit dieser Situation umzugehen.

Gibt es einen anderen besseren Weg, dies zu handhaben als float64 in Integer zu konvertieren?

Antwort

5

JSON, genau wie Javascript, unterscheidet sich nicht zwischen Ganzzahlen und Zahlen.

Wenn Dart 1234.00 anders behandelt als 1234, werden Annahmen über den Wert gemacht, der von JSON specification nicht unterstützt wird.

Während Go in der Tat Marschall richtig FLOAT64, einen Weg mit Dart der Annahme, um das Problem des Erhaltens ist durch die Marshaler interface auf Ihre eigene Art der Umsetzung:

type Number float64 

func (n Number) MarshalJSON() ([]byte, error) { 
    // There are probably better ways to do it. It is just an example 
    return []byte(fmt.Sprintf("%f", n)), nil 
} 

Und dann können Sie Ihre eigenen Number Typ, anstelle von float64, in den Strukturen, die Sie Marschall werden. Auf diese Weise können Sie sicherstellen, dass Ihre Zahlen immer mit einem Dezimalpunkt gemarshallt werden.

Arbeitsbeispiel auf Playground

+0

Danke für die Lösung. Ich denke, das sollte am Dartende gelöst werden. Es scheint, dass eine Ganzzahl in Dart keinem Double zugewiesen werden kann. Dies scheint mir eine Anomalie zu sein, aber ich akzeptiere, dass ich zumindest aus einer theoretischen Perspektive falsch liege (verstümmelt, niedergeschlagen, etc.). Die Lösung, die ich derzeit habe, ist wie folgt: "double dAcctBal = (mActctData ['D_AcctBal'] als num)/1;" (wobei mAcctData die Map ist, bei der "D_AcctBal" eine Ganzzahl oder ein Double sein kann, abhängig davon, ob es sich um eine ganze Zahl handelt). Diese Lösung erscheint mir ein bisschen wie ein Hack, aber wenn eine Integer nicht direkt einem Double zugewiesen werden kann? –

+0

Ja, ich stimme zu, dass es am besten wäre, es am Dartende zu lösen. Ich würde Ihnen gerne eine solche Lösung anbieten, wenn ich das wüsste, aber meine Erfahrung mit Dart ist * sehr * begrenzt. Vielleicht kann jemand mit mehr Wissen eine idiomatische Dart-Lösung finden. – ANisus

+0

JSON gibt die Semantik seiner Zahlenliterale nicht an, daher ist es nicht korrekter, doppelte als ganze Zahlen zu verwenden. Dart hat zwei Nummerntypen.Alles, was einen Dezimalpunkt oder einen Exponentialteil enthält, muss ein Double sein, und alles andere wird als Integer geparst, was in Dart mehr Präzision als Doppel liefert. Dies bewahrt so viele Informationen wie möglich von der JSON-Nummer. Sie müssen jedoch .toDouble manuell verwenden, wenn Sie möchten, dass alle Zahlen verdoppelt werden. – lrn

1

Es wird angezeigt (für mich) die Lösung zu sein. Die Integer-Methode toDouble() funktioniert auch mit "num" (oder umgekehrt). Es scheint mir, dass bei der Arbeit mit JSON und monetären Werten, die von Dart entweder als double oder int interpretiert werden können, es notwendig ist, "as num" zu verwenden und dann die eingebaute Methode toDouble() zu verwenden.

Beispiel (Go):

type cuAcctRow struct { 
     ..... 
    D_AcctBal float64 
     ..... 
} 
    if baJsAcctDet, oOsError = json.Marshal(uAcctRow); oOsError != nil { 

Beispiel (Dart):

Map mAcctData = json.parse(sResponse); 

double dAcctBal = (mAcctData['D_AcctBal'] as num).toDouble(); 

Ich weiß nicht, warum Dart keine direkte Zuordnung von integer erlaubt zu verdoppeln, aber ich bin Sicher gibt es einen guten Grund.

+0

Ein sehr guter Grund. Typ Anmerkungen in Dart sind optional, und sie werden als Zusicherungen behandelt (sie werden im Produktionsmodus ignoriert). Das bedeutet, dass eine Variable keinen Typ hat. Daher muss die Zuweisung einer Ganzzahl zu einer als Double deklarierten Variablen genauso funktionieren, unabhängig davon, ob die Variable doppelt ("double x") oder nur dynamisch ("var x") deklariert ist. Dies verhindert eine implizite Konvertierung. Im aktivierten Modus wird die Zuweisung überprüft, und da 'int' kein Subtyp von 'double' ist, schlägt die Assertion des Typs fehl. Sie müssen eine explizite n.toDouble() machen. – lrn

+0

@lrn: Danke für die Erklärung. Ich "sollte" das studieren. Es hat mich verwirrt, aber ich denke, es gibt ein paar Faktoren. Während ich davon jetzt weiter gegangen bin, vermute ich, dass meine kleine "Lösung" in Ordnung ist. (wie num) .toDouble() ist nicht sehr belastend, aber aus praktischer Sicht erschien es mir seltsam, dass ein Int, der in Reichweite zu einem Double perfekt kompatibel ist, nicht direkt einem Double zugeordnet werden konnte. Da dieses kleine Problem relativ einfach ist, sind ein paar Faktoren beteiligt (einschließlich JS, nehme ich an - vielleicht indirekt). –