Heim > Backend-Entwicklung > Golang > Wie glätte ich anonyme Schnittstellenfelder in der Go-JSON-Serialisierung?

Wie glätte ich anonyme Schnittstellenfelder in der Go-JSON-Serialisierung?

Susan Sarandon
Freigeben: 2024-10-29 06:52:02
Original
438 Leute haben es durchsucht

How to Flatten Anonymous Interface Fields in Go JSON Serialization?

Reduzieren von JSON-Strukturen mit anonymen Mitgliedern in Go

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.

Das Problem

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

Wie Sie sehen können, wird das anonyme Mitglied „Anything“ im JSON als benanntes Feld behandelt, was nicht das beabsichtigte Verhalten ist.

Die Lösung

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

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!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage