In Go werden anonyme Strukturfelder normalerweise so gemarshallt, als ob ihre inneren exportierten Felder Felder in der äußeren Struktur wären. Dies kann jedoch zu unerwartetem Verhalten führen, wenn Strukturen mit anonymen Mitgliedern vom Typ interface{} gemarshallt werden.
Betrachten Sie das folgende Beispiel:
<code class="go">type User struct { Id int `json:"id"` Name string `json:"name"` } type Session struct { Id int `json:"id"` UserId int `json:"userId"` } type Anything interface{} type Hateoas struct { Anything Links map[string]string `json:"_links"` } func MarshalHateoas(subject interface{}) ([]byte, error) { h := &Hateoas{subject, make(map[string]string)} switch s := subject.(type) { case *User: h.Links["self"] = fmt.Sprintf("http://user/%d", s.Id) case *Session: h.Links["self"] = fmt.Sprintf("http://session/%d", s.Id) } return json.MarshalIndent(h, "", " ") } func main() { u := &User{123, "James Dean"} s := &Session{456, 123} json, err := MarshalHateoas(u) if err != nil { panic(err) } else { fmt.Println("User JSON:") fmt.Println(string(json)) } json, err = MarshalHateoas(s) if err != nil { panic(err) } else { fmt.Println("Session JSON:") fmt.Println(string(json)) } }</code>
Bei der Ausführung In diesem Code ist der resultierende JSON nicht wie erwartet:
<code class="json">User JSON: { "Anything": { "id": 123, "name": "James Dean" }, "_links": { "self": "http://user/123" } } Session JSON: { "Anything": { "id": 456, "userId": 123 }, "_links": { "self": "http://session/456" } }</code>
Wie Sie sehen können, wird das anonyme Mitglied „Anything“ im JSON als benanntes Feld behandelt, was nicht das beabsichtigte Verhalten ist.
Um das anonyme Mitglied zu reduzieren und die gewünschte JSON-Struktur zu erreichen, können wir das Reflect-Paket verwenden, um die Felder der Struktur zu durchlaufen und sie einer Map[string]-Schnittstelle{} zuzuordnen. Dadurch können wir die flache Struktur der ursprünglichen Struktur beibehalten, ohne neue Felder einzuführen.
Der aktualisierte Code lautet wie folgt:
<code class="go">import ( "encoding/json" "fmt" "reflect" ) // ... (rest of the code remains the same) func MarshalHateoas(subject interface{}) ([]byte, error) { links := make(map[string]string) out := make(map[string]interface{}) subjectValue := reflect.Indirect(reflect.ValueOf(subject)) subjectType := subjectValue.Type() for i := 0; i < subjectType.NumField(); i++ { field := subjectType.Field(i) name := subjectType.Field(i).Name out[field.Tag.Get("json")] = subjectValue.FieldByName(name).Interface() } switch s := subject.(type) { case *User: links["self"] = fmt.Sprintf("http://user/%d", s.Id) case *Session: links["self"] = fmt.Sprintf("http://session/%d", s.Id) } out["_links"] = links return json.MarshalIndent(out, "", " ") }</code>
Mit dieser Änderung wird der resultierende JSON korrekt abgeflacht:
<code class="json">User JSON: { "id": 123, "name": "James Dean", "_links": { "self": "http://user/123" } } Session JSON: { "id": 456, "userId": 123, "_links": { "self": "http://session/456" } }</code>
Das obige ist der detaillierte Inhalt vonWie glätte ich anonyme Schnittstellenfelder in der Go-JSON-Serialisierung?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!