2015-07-17 23 views
9

Ich möchte Elemente hinzufügen, die nicht in den Strukturen Definitionen sind, ohne einen anderen Strukturtyp zu erstellen. Zum BeispielGolang modifizieren Json ohne Struktur

Struct.Extra1 = Nested{"yy"} 
Struct.Nested.Extra2 = "zz" 

Welche

{ 
    "Value": "xx", 
    "Value1": "xx", 
    "Extra1": { 
     "Something", "yy" 
    }, 
    "Nest": { 
     "Something": "xx", 
     "Extra2": "zz" 
    } 
} 

Solution1 führt: Ich dachte omitempty hinzuzufügen, dies zu erreichen, aber es macht den structs komplex.

type Struct struct { 
    Value string 
    Value1 string 
    Nest Nested 
    Extra1 Nested `json:"omitempty"` 
} 

type Nested struct { 
    Something string 
    Extra2 string `json:"omitempty"` 
} 

Solution2:

myextras := make(map[string]interface{}) 
// get Struct.Nested in map[string]interface{} format 
myextras = Struct.Nest 
myextras["Extra2"] = "zz" 

// get Struct in map[string]interface{} format 
struct["Nest"] = myextras 
struct["Extra1"] = Nested{"yy"} 

// solves the problem with lots of type casting but doesn't support json tag naming 

Gibt es eine bessere Lösung verschachtelte Elemente hinzuzufügen, die mit json-Tag-Unterstützung in Struktur-Datentyp dargestellt werden, nicht und könnte für die Ausgabe an Benutzer verwendet werden.

Antwort

6

zu dieser Antwort Basierend. Can I use MarshalJSON to add arbitrary fields to a json encoding in golang?

Sie etwas tun könnte, wie (Demo : http://play.golang.org/p/dDiTwxhoNn):

package main 

import (
    "encoding/json" 
    "fmt" 
    "log" 
) 

type Book struct { 
    Title string 
    Author string 

    // extra is used for additional dynamic element marshalling 
    extra func() interface{} 
} 

type FakeBook Book 

func (b *Book) SetExtra(fn func() interface{}) { 
    b.extra = fn 
} 

func (b *Book) MarshalJSON() ([]byte, error) { 
    if b.extra == nil { 
     b.extra = func() interface{} { return *b } 
    } 

    return json.Marshal(b.extra()) 
} 

func main() { 
    ms := &Book{ 
     Title: "Catch-22", 
     Author: "Joseph Heller", 
    } 

    ms.SetExtra(func() interface{} { 
     return struct { 
      FakeBook 
      Extra1 struct { 
       Something string `json:"something"` 
      } `json:"extra1"` 
     }{ 
      FakeBook: FakeBook(*ms), 
      Extra1: struct { 
       Something string `json:"something"` 
      }{ 
       Something: "yy", 
      }, 
     } 
    }) 

    out, err := json.MarshalIndent(ms, "", " ") 
    if err != nil { 
     log.Fatalln(err) 
    } 
    fmt.Println(string(out)) 

    mb := &Book{ 
     Title: "Vim-go", 
     Author: "Fatih Arslan", 
    } 

    mb.SetExtra(func() interface{} { 
     return struct { 
      FakeBook 
      Something string `json:"something"` 
     }{ 
      FakeBook: FakeBook(*mb), 
      Something: "xx", 
     } 
    }) 

    out, err = json.MarshalIndent(mb, "", " ") 
    if err != nil { 
     log.Fatalln(err) 
    } 
    fmt.Println(string(out)) 

    mc := &Book{ 
     Title: "Another-Title", 
     Author: "Fatih Arslan", 
    } 

    out, err = json.MarshalIndent(mc, "", " ") 
    if err != nil { 
     log.Fatalln(err) 
    } 
    fmt.Println(string(out)) 
} 
+1

meine absolut gültige bearbeiten da von den Mods als „abgelehnt wurde, sollte sei ein Kommentar "(auch wenn das eine große Platzverschwendung als Kommentar ist) - beachte, dass du' json: "-" 'nicht brauchst, um das Serialisieren zu verhindern, da es nicht exportiert wird. –

+0

Danke @NateFinch für die Info, macht Sinn. Ich bearbeite es in Ihrem Auftrag. –

2

ja. Es gibt einen Typ json.Raw, der kein struct aber [] Byte ist. Sie können es in jeder Art von Marshal/Unmarshal aus Struct verwalten.

+0

könnten Sie den Code hinzufügen '„Extra2“' in json.Raw Format bieten das ist der schwierige Teil – Thellimist

2

Die Karte Ansatz der einzige vernünftige Weg, es zu tun, alles andere (wie json.RawMessage Felder würden ohnehin zusätzliche Rangier Schritt erfordern

Verwandte Themen