Benutzerdefinierte MarshalJSON() nie aufgerufen wird, wird in Go
Habe ich geschrieben benutzerdefinierte Versionen von MarshalJSON
und UnmarshalJSON
. Meine UnmarshalJSON
aufgerufen wird, wie ich es möchte, aber ich kann es nicht zu funktionieren mit MarshalJSON
. Hier ist code, der fasst mein problem:
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"os"
)
type myStruct struct {
Data string `json:"data"`
}
func (s *myStruct) MarshalJSON() ([]byte, error) {
return []byte(`{"data":"charlie"}`), nil
}
func (s *myStruct) UnmarshalJSON(b []byte) error {
//Insert the string directly into the Data member
return json.Unmarshal(b, &s.Data)
}
func main() {
//Create a struct with initial content "alpha"
ms := myStruct{"alpha"}
//Replace content with "bravo" using custom UnmarshalJSON() (SUCCESSFUL)
if err := json.NewDecoder(bytes.NewBufferString(`"bravo"`)).Decode(&ms); err != nil {
log.Fatal(err)
}
//Use custom MarshalJSON() to get "charlie" back (UNSUCCESSFUL)
if err := json.NewEncoder(os.Stdout).Encode(ms); err != nil {
log.Fatal(err)
}
//Trying another method (UNSUCCESSFUL)
if ret, err := json.Marshal(ms); err != nil {
log.Fatal(err)
} else {
fmt.Println(string(ret))
}
//Verify that the Marshaler interface is correctly implemented
var marsh json.Marshaler
marsh = &ms
ret, _ := marsh.MarshalJSON()
fmt.Println(string(ret)) //Prints "charlie"
}
Kurz gesagt, das Programm codiert die struct
"automatisch" in zwei Arten, und dann schließlich fordert MarshalJSON
manuell. Die Antwort, die ich will, ist "charlie"
. Läuft der code erzeugt die folgende Ausgabe:
{"data":"bravo"}
{"data":"bravo"}
{"data":"charlie"}
Versuchen Sie es bei Gehen Spielplatz: http://play.golang.org/p/SJ05S8rAYN
- Nur ersetzt
ms
zu&ms
im erfolglosen Beispiele und es funktioniert für mich: play.golang.org/p/VfZYuNkjmq. Aber ich kann nicht erklären, warum, nur Vorschlag, wir sollten also warten, bis jemand, der genau weiß,. - Kavu hat die Lösung. Ihre Methode gilt für *myStruct, nicht myStruct.
- Danke! Kann nicht glauben, dass ich verpasst, dass. Eigentlich habe ich getestet, die Stunden vor, aber konnte es nicht zu funktionieren. Aber ich hatte wohl ein bug dann wohl so. 🙂
- by the way, ich bevorzuge die Initialisierung aller Strukturen mit
&myStruct{...}
konstruieren. Mich nie im Stich gelassen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
In diesem Teil des Codes
ms
kopiert wird in eininterface{}
variable:Das problem ist, dass diese variable nicht implementiert
json.Marshaler
- Schnittstelle, daMarshalJSON
ist nicht in der die Methode set fürmyStruct
(nur für*myStruct
).Das Update ist entweder (a) machen Sie Ihre
MarshalJSON
- Methode eine nicht-Zeiger-receiver (was bedeutet, es wird eine Kopie der struct: möglicherweise teuer, wenn es groß ist), oder (b) marshal einen Zeiger auf die struct (als Kavu erwähnt in einem Kommentar).Den Grund für dieses Verhalten ist, Gehen Sie nicht lassen Sie einen Zeiger auf den gespeicherten Wert innerhalb einer interface-variable, stattdessen erfordern Sie eine Kopie des Werts, Wann immer Sie darauf zugreifen möchten. Während die Sprache die syntaktischen Zucker zu konvertieren
ms.MarshalJSON()
in(&ms).MarshalJSON()
als ein Weg, um Zugriff auf die Methode mit einem Zeiger-Empfänger, das kann nicht getan werden, für den ein Wert, gespeichert in einer interface-Variablen. Aus diesem Grund, die Methode wird nicht als in seiner Methode stellen.&myStruct{}
ist eine lebensrettende Muster