2014-07-16 17 views
12

Das Problem zu lösen, ich versuche, ist, dass ich ein Modell einer Gemeinschaft, die wie diese eine Menge Informationen, und esEine Struktur mit mehreren json Darstellungen in Golang

type Community struct { 
    Name string 
    Description string 
    Sources []Source 
    Popularity int 
    FavoriteCount int 
    Moderators []string 
    Children []Community 
    Tracks []Track 
} 

Gemeinschaften sieht sind halte Szenarien, wenn Ich möchte nur einen Teil der Beschreibung zurückgeben, z. B. wenn ich eine Liste mit Trendgemeinschaften zurücksende. In diesem Fall würde ich nur

type Community struct { 
    Name string 
    Description string 
    Popularity int 
    FavoriteCount int 
} 

Der einzige Weg, zurückzukehren Ich möchte, dies zu tun, einen neuen Typ nur die Felder enthalten, denken zu erstellen ist und eine bequeme Methode schreiben, die eine Gemeinschaft nimmt und diese Art, aber im Wesentlichen ein neues Objekt erstellen und diese Felder nach Wert kopieren, gibt es eine bessere Möglichkeit, dies zu tun?

Ich bin mir der json:"-" Syntax bewusst, aber ich bin mir nicht sicher, wie Sie dies von Fall zu Fall tun können, da ich immer noch das vollständige Objekt zurückgeben muss, vielleicht einen anderen Typ, der typecasted ist ?

+0

Eine Möglichkeit, einen benutzerdefinierten http://golang.org/pkg/encoding/json/#Marshaler zusammen mit einem internen Konfigurationsfeld zu implementieren, ist zu spezifizieren Welche Felder Ihrer Struktur möchten Sie ausgeben? –

Antwort

2

Ich entwickelte eine Bibliothek, die Sie in dieser Hinsicht helfen: Sheriff

Sie können Ihre Struktur Felder mit speziellen Tags mit Anmerkungen versehen und Sheriff rufen die gegebene Struktur in eine Teilmenge davon zu transformieren.Danach können Sie json.Marshal() oder was auch immer Sie einmarschieren wollen, anrufen.

Ihr Beispiel wäre so einfach worden wie:

type Community struct { 
    Name   string  `json:"name" groups:"trending,detail"` 
    Description string  `json:"description" groups:"trending,detail"` 
    Sources  []Source `json:"sources" groups:"detail"` 
    Popularity int   `json:"popularity" groups:"trending,detail"` 
    FavoriteCount int   `json:"favorite_count" groups:"trending,detail"` 
    Moderators []string `json:"moderators" groups:"detail"` 
    Children  []Community `json:"children" groups:"detail"` 
    Tracks  []Track  `json:"tracks" groups:"detail"` 
} 

communities := []Community{ 
    // communities 
} 

o := sheriff.Options{ 
    Groups: []string{"trending"}, 
} 

d, err := sheriff.Marshal(&o, communities) 
if err != nil { 
    panic(err) 
} 

out, _ := json.Marshal(d) 
3

Ja, das ist der einzige Weg, den ich kenne, wenn ich den Default Marshaller benutze. Die einzige andere Option ist, wenn Sie Ihren eigenen JsonMarshaller erstellen.

type Community struct { 

} 

type CommunityShort Community 

func (key *Community) MarshalJSON() ([]byte, os.Error) { 
    ... 
} 

func (key *Community) UnmarshalJSON(data []byte) os.Error { 
... 
} 


func (key *CommunityShort) MarshalJSON() ([]byte, os.Error) { 
    ... 
} 

func (key *CommunityShort) UnmarshalJSON(data []byte) os.Error { 
... 
} 
12

meine Antwort bearbeiten - fand einen besseren Weg:

Dieses ist ein cooler Ansatz:

http://attilaolah.eu/2014/09/10/json-and-struct-composition-in-go/

beinhaltet eine Art von Maskierung Struktur zu schaffen.

Hier ist das Beispiel in dem Artikel:

type User struct { 
    Email string `json:"email"` 
    Password string `json:"password"` 
    // many more fields… 
} 

type omit *struct{} 

type PublicUser struct { 
    *User 
    Password omit `json:"password,omitempty"` 
} 

// when you want to encode your user: 
json.Marshal(PublicUser{ 
    User: user, 
}) 
2

Ich werde dir einen anderen Ansatz präsentieren, die ich entwickelt habe. Ich denke, es ist viel sauberer. Der einzige Nachteil ist eine etwas komplizierte Objektinitialisierung, aber im Gebrauch ist es sehr gestrafft.

Der wichtigste Punkt ist, dass Sie nicht Ihr JSON-View-Objekt auf dem ursprünglichen Objekt zu stützen und dann Elemente drin, aber andersherum versteckt, sich einen Teil des ursprünglichen Objekts machen:

type CommunityBase struct { 
    Name string 
    Description string 
} 

type Community struct { 
    CommunityBase 
    FavoriteCount int 
    Moderators []string 
} 

var comm = Community{CommunityBase{"Name", "Descr"}, 20, []string{"Mod1","Mod2"}} 

json.Marshal(comm) 
//{"Name":"Name","Description":"Descr","FavoriteCount":20,"Moderators":["Mod1","Mod2"]} 

json.Marshal(comm.CommunityBase) 
//{"Name":"Name","Description":"Descr"} 

Und das ist alles, wenn Sie nur eine Ansicht benötigen, oder wenn Ihre Ansichten schrittweise erweitert werden.

Aber wenn Sie Ihre Ansichten nicht vererbt werden können, werden Sie zu einer Art Mixins greifen müssen, so können Sie von ihnen eine kombinierte Ansicht machen:

type ThingBaseMixin struct { 
    Name string 
} 

type ThingVisualMixin struct { 
    Color string 
    IsRound bool 
} 

type ThingTactileMixin struct { 
    IsSoft bool 
} 

type Thing struct { 
    ThingBaseMixin 
    ThingVisualMixin 
    ThingTactileMixin 
    Condition string 
    visualView *ThingVisualView 
    tactileView *ThingTactileView 
} 

type ThingVisualView struct { 
    *ThingBaseMixin 
    *ThingVisualMixin 
} 

type ThingTactileView struct { 
    *ThingBaseMixin 
    *ThingTactileMixin 
} 

func main() { 
    obj := Thing { 
     ThingBaseMixin: ThingBaseMixin{"Bouncy Ball"}, 
     ThingVisualMixin: ThingVisualMixin{"blue", true}, 
     ThingTactileMixin: ThingTactileMixin{false}, 
     Condition: "Good", 
    } 
    obj.visualView = &ThingVisualView{&obj.ThingBaseMixin, &obj.ThingVisualMixin} 
    obj.tactileView = &ThingTactileView{&obj.ThingBaseMixin, &obj.ThingTactileMixin} 

    b, _ := json.Marshal(obj) 
    fmt.Println(string(b)) 
//{"Name":"Bouncy Ball","Color":"blue","IsRound":true,"IsSoft":false,"Condition":"Good"} 

    b, _ = json.Marshal(obj.ThingVisualMixin) 
    fmt.Println(string(b)) 
//{"Color":"blue","IsRound":true} 

    b, _ = json.Marshal(obj.visualView) 
    fmt.Println(string(b)) 
//{"Name":"Bouncy Ball","Color":"blue","IsRound":true} 

    b, _ = json.Marshal(obj.tactileView) 
    fmt.Println(string(b)) 
//{"Name":"Bouncy Ball","IsSoft":false} 
} 

Hier habe ich eine Ansicht hinzugefügt haben das Objekt in, aber wenn Sie möchten, können Sie es nur schaffen, wenn Marshal Aufruf:

json.Marshal(ThingVisualView{&obj.ThingBaseMixin, &obj.ThingVisualMixin}) 

Oder auch ohne vorherige Typdeklaration:

json.Marshal(struct{*ThingBaseMixin;*ThingVisualMixin}{&obj.ThingBaseMixin,&obj.ThingVisualMixin}) 
+0

Dies ist ein ziemlich interessanter Ansatz. Der zweite Teil Ihrer Antwort erinnert mich in gewisser Weise an PHP-Merkmale. –

+0

Ein interessanter Moment ist, dass Sie das Originalobjekt direkt über die Ansichten bearbeiten können. Vielleicht kann dieser Ansatz auch in irgendeinem anderen Bereich von Nutzen sein. – user

Verwandte Themen