Maison >développement back-end >Golang >Comment préserver le regroupement personnalisé dans les structures Go Embedded ?

Comment préserver le regroupement personnalisé dans les structures Go Embedded ?

DDD
DDDoriginal
2024-12-17 19:07:10857parcourir

How to Preserve Custom Marshalling in Go Embedded Structs?

Préserver le regroupement personnalisé pour les structures intégrées

Dans Go, l'intégration d'une structure dans une autre est un moyen courant d'hériter de fonctionnalités. Cependant, lorsque la structure intégrée possède une méthode MarshalJSON() personnalisée, des problèmes peuvent survenir. Cet article explore une solution à ce défi, garantissant que la structure externe peut rassembler ses champs normalement tout en tirant parti du marshalling personnalisé de la structure intégrée.

Considérez les structures suivantes :

type Person struct {
    Name string `json:"name"`
}

type Employee struct {
    *Person
    JobRole string `json:"jobRole"`
}

Normalement, le regroupement d'un employé vers JSON produirait le résultat attendu :

p := Person{"Bob"}
e := Employee{&p, "Sales"}
output, _ := json.Marshal(e)
fmt.Printf("%s\n", string(output))
// Output: {"name":"Bob","jobRole":"Sales"}

Cependant, l'introduction d'un fichier personnalisé La méthode MarshalJSON() pour la structure Person intégrée modifie ce comportement :

func (p *Person) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct{ Name string `json:"name"` }{Name: strings.ToUpper(p.Name)})
}

Maintenant, le rassemblement de l'employé produit uniquement le nom en majuscule :

output, _ := json.Marshal(e)
fmt.Printf("%s\n", string(output))
// Output: {"name":"BOB"}

Pour résoudre ce problème, on peut tenter de ajoutez une méthode MarshalJSON() à la structure Employee externe. Cependant, cette approche nécessite la connaissance du marshalling personnalisé du type intégré, ce qui n'est pas toujours pratique.

Une solution plus générique consiste à implémenter directement MarshalJSON() sur le type externe :

// Note: not on Person
func (e *Employee) MarshalJSON() ([]byte, error) {
    inner, err := json.MarshalIndent((*e.Person).(*Person), "", "    ")
    if err != nil {
        return nil, err
    }

    b := []byte(strings.Replace(string(inner), "}", "}", -1))
    b = append(b, []byte(`,"jobRole":"`+e.JobRole+`"}`)...)

    return b, nil
}

Cette approche appelle la méthode MarshalJSON() de la structure intégrée, convertit le résultat en carte et ajoute les champs de la structure externe pour produire la sortie JSON souhaitée. Notez qu'elle ne manipule pas le marshalling personnalisé de la structure intégrée.

Vous pouvez également utiliser une approche basée sur la réflexion :

func (e *Employee) MarshalJSON() ([]byte, error) {
    v := reflect.ValueOf(e).Elem()
    vf := v.FieldByName("Person")
    tmp, err := json.MarshalIndent(vf.Interface(), "", "    ")
    if err != nil {
        return nil, err
    }

    return []byte(strings.Replace(string(tmp), "}", `,"jobRole":"`+e.JobRole+`"}`, -1)), nil
}

Cette méthode utilise la réflexion pour accéder à la valeur et au champ de la structure intégrée. , permettant un marshalling personnalisé sans s'appuyer sur des connaissances structurelles.

En implémentant MarshalJSON() sur le type externe, cette approche garantit que les deux et les champs de la structure externe sont correctement marshalés, préservant le résultat souhaité.

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!

Déclaration:
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