Unmarshaling In einem Interface{} und Anschließend Ausführen, Geben Sie Behauptung
Bekomme ich eine string
durch ein rabbitmq-message-system. Vor dem senden,
Benutze ich json.Marshal
konvertieren, das Ergebnis zu string
und senden durch
rabbitmq.
Den Strukturen, die ich konvertieren und senden kann: (die Namen geändert und die Größe der Strukturen, aber es sollte keine Rolle spielen)
type Somthing1 struct{
Thing string `json:"thing"`
OtherThing int64 `json:"other_thing"`
}
oder
type Somthing2 struct{
Croc int `json:"croc"`
Odile bool `json:"odile"`
}
Die Nachricht geht durch perfekt als string
gedruckt
auf der anderen Seite (server)
Bis jetzt funktioniert alles.
Jetzt versuche ich, konvertieren Sie Sie zurück in Ihre Strukturen und die für die Geltendmachung der Arten.
ersten Versuch durch:
func typeAssert(msg string) {
var input interface{}
json.Unmarshal([]byte(msg), &input)
switch input.(type){
case Somthing1:
job := Somthing1{}
job = input.(Somthing1)
queueResults(job)
case Somthing2:
stats := Somthing2{}
stats = input.(Somthing2)
queueStatsRes(stats)
default:
}
Funktioniert das nicht. Beim Drucken die Art des input
nach Unmarshaling
es ich bekomme map[string]interface{}
(?!?)
- und noch seltsamer, als dass der map-key ist der string, den ich bekam und der map-Wert leer ist.
Habe ich einige andere versuche wie:
func typeAssert(msg string) {
var input interface{}
json.Unmarshal([]byte(msg), &input)
switch v := input.(type){
case Somthing1:
v = input.(Somthing1)
queueResults(v)
case Somthing2:
v = input.(Somthing2)
queueStatsRes(v)
default:
}
und auch versucht, das schreiben der Schalter, wie schon erläutert, die in dieser Antwort:
Golang: nicht Typ-Schalter auf non-Schnittstelle Wert
switch v := interface{}(input).(type)
immer noch ohne Erfolg...
Irgendwelche Ideen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den Standard-Typen, die
json
Paket Unmarshals in der Anzeige in derUnmarshal
Funktion DokumentationDa bist du unmarshaling in eine
interface{}
die zurückgegebenen Typen werden nur aus diesem Satz. Diejson
Paket gar nicht kenntSomething1
undSomething2
. Sie müssen entweder konvertieren vonmap[string]interface{}
Sie, dass das json-Objekt wird in deren Marshalling rückgängig gemacht wurde, oder unmarshal direkt in den struct-Typ Sie wollen.Wenn Sie nicht wollen, zu tun ist, entpacken Sie die Dateien aus einer generischen Schnittstelle, oder irgendwie tag die Daten, damit Sie wissen, was zu erwarten ist, könnte man iterativ nehmen Sie die json und versuchen, unmarshal es in jeder Art Sie wollen.
Sie können auch pack die in einen wrapper-Struktur zu tun, die unmarshaling für Sie:
http://play.golang.org/p/Trwd6IShDW
map[string]interface{}
wenn ich nicht weiß, welche Taste zu verwenden? @JimBinterface{}
, und Sie können nicht behaupten, eine Schnittstelle, die ein Typ, der ist es nicht. Nehmen Sie die Daten aus der Karte, die Sie bekommen, und erstellen Sie eine neue Struktur der Art, die Sie wollen.Die Sie gefunden haben eine typische json vs typisierte Sprache problem!
Da json nicht typisiert ist und schemaless, es ist nicht möglich zu folgern, was Daten "unter die Schnur", ohne tatsächlich Decodierung.
Also Ihre einzige option ist unmarshal in eine
interface{}
das erzeugt immer einenmap[string]interface{}
. Sie könnte eine Reflexion der Magie zu bauen, die endgültige Struktur, aber das ist viel manuelle Arbeit und Fehler anfällig.Hier sind einige mögliche Lösungen:
Quick 'n' dirty
Lassen die
json
Paket die spiegelung Zeug. Versuch unmarshal in jeder erwartete Typ:Bauen Sie Ihre eigene "Art system" auf der Oberseite des json -
Verzögern die Codierung, bis Sie wissen, was drin ist. Verwenden Sie diese Struktur als Zwischenprodukt Darstellung Ihrer Daten:
Marschall:
Unmarshal:
Verwenden ein typisiertes Serialisierungsformat
Type
könnte alles sein, qualifiziert sich als ein Bezeichner (z.B. verschiedene int-Werte). Es sieht ganz komisch aus, weil es wirklich nur ein hack zum umgehen der Einschränkungen von json.json.RawMessage
ist genau die richtige Lösung für diese Art von problem.