Maison > développement back-end > Golang > Comment aplatir les champs d'interface anonymes dans la sérialisation Go JSON ?

Comment aplatir les champs d'interface anonymes dans la sérialisation Go JSON ?

Susan Sarandon
Libérer: 2024-10-29 06:52:02
original
534 Les gens l'ont consulté

How to Flatten Anonymous Interface Fields in Go JSON Serialization?

Aplatissement des structures JSON avec des membres anonymes dans Go

Dans Go, les champs de structure anonymes sont généralement marshalés comme si leurs champs exportés internes étaient des champs dans la structure externe. Cependant, cela peut conduire à un comportement inattendu lors du marshaling de structures avec des membres anonymes de type interface{}.

Le problème

Considérez l'exemple suivant :

<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>
Copier après la connexion

Lors de l'exécution ce code, le JSON résultant n'est pas comme prévu :

<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>
Copier après la connexion

Comme vous pouvez le voir, le membre anonyme Anything est traité comme un champ nommé dans le JSON, ce qui n'est pas le comportement prévu.

La solution

Pour aplatir le membre anonyme et obtenir la structure JSON souhaitée, nous pouvons utiliser le package Reflect pour parcourir les champs de la structure et les mapper à une interface map[string]{}. Cela nous permet de conserver la structure plate de la structure d'origine sans introduire de nouveaux champs.

Le code mis à jour est le suivant :

<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>
Copier après la connexion

Avec cette modification, le JSON résultant est correctement aplati :

<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>
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal