web-dev-qa-db-fra.com

Comment puis-je fusionner deux structures dans Golang?

J'ai deux structures anonymes json-marshallable.

a := struct {
    Name string `json:"name"`
}{"my name"}

b := struct {
    Description string `json:"description"`
}{"my description"}

Est-il possible de les fusionner dans JSON pour obtenir quelque chose comme ça:

{
    "name":"my name",
    "description":"my description"
}
6
Dmitry Kapsamun

Vous pouvez incorporer les deux structures dans un autre .

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

type description struct {
    Description string `json:"description"`
}

type combined struct {
    name
    description
}

Le paquet JSON traitera les structures incorporées un peu comme des unions, mais cela peut devenir maladroit assez rapidement.

10
nothingmuch

C'est un peu compliqué mais je suppose que vous pourriez faire quelque chose comme ceci:

    a := struct {
        Name string `json:"name"`
    }{"my name"}

    b := struct {
        Description string `json:"description"`
    }{"my description"}

    var m map[string]string

    ja, _ := json.Marshal(a)
    json.Unmarshal(ja, &m)
    jb, _ := json.Marshal(b)
    json.Unmarshal(jb, &m)

    jm, _ := json.Marshal(m)
    fmt.Println(string(jm))
7
Franck Jeannin

Vous pouvez fusionner deux struct comme ceci:

package main

import (
    "fmt"
    "encoding/json"
)


type b struct {
    Name string  `json:"name"`
    Description string
    Url string
}

type a struct {
    *b
    MimeType string  `json:"mimeType"`
}

func main() {
    bc := b{"test", "testdecription", "testurl"}
    ac := a{nil, "jpg"}

    ac.b = &bc

    js, _ := json.Marshal(ac)

    fmt.Println(string(js) )
}
3
Adrien Parrochia

Go est tout au sujet de la composition sur l'héritage. Malheureusement, vous utilisez des structures anonymes, mais étant donné que vous essayez clairement de les ordonner, il vaut mieux les définir en tant que types:

type name struct {
    Name string `json:"name"`
}
type desc struct {
    Description string `json:"description"`
}

Vous pouvez les initialiser de la même manière que vous le faites actuellement, mais au lieu de struct{<fields>}{init}, vous écrivez simplement

a := name{"foo"}
b := desc{"Description"}

Vous pouvez ensuite les combiner à votre guise en écrivant:

c := struct {
    name
    description
}{a, b}

Une bizarrerie (qui pourrait vous faire trébucher au début) à laquelle vous devez vous habituer lorsque vous composez des types comme ceci est la façon dont vous initialisez les membres. Imaginons que vous décidiez de créer un type combinant les deux autres structures:

type foo struct {
    name
    description
}

Vous ne pouvez pas l'initialiser comme ceci:

o := foo{"Name value", "description value"}

Go se plaindra de votre utilisation de la chaîne type en tant que type name. Vous devrez écrire quelque chose comme ceci:

o := foo{
    name{"Name value"},
    description{Description: "Description val"},//optional with field names
}

Un composite en ligne construit à l'aide d'objets existants (cf c := struct{}{a, b}) le fait déjà.
Selon ce que vous essayez de faire, il est parfois plus facile d'écrire quelque chose comme ceci:

func (s *MyCompositeType) CopyName(n name) {
    s.Name = n.Name
    //copy other fields
}

Cela facilite la vie lorsque vous imbriquez des types composites à plusieurs niveaux.

3