2015-07-17 23 views
9
type Struct struct { 
    Value string `json:"value"` 
    Value1 string `json:"value_one"` 
    Nest Nested `json:"nest"` 
} 

type Nested struct { 
    Something string `json:"something"` 
} 

Başka bir yapı türü oluşturmadan yapı tanımlarında olmayan elemanlar eklemek istiyorum. ÖrneğinGolang, json yapısını değiştirmeden yapılandırın.

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

için

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

Solution1 sonuçlanacaktır Hangi: Bunu başarmak için omitempty ekleyerek düşündüm ama yapılar kompleks hale getirir.

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 

json etiketi desteği ile yapı veri türü temsil edilmeyen ve kullanıcıya çıkış için kullanılabilecek iç içe unsurları eklemek için daha iyi bir çözüm var mı.

cevap

6

Bu yanıt dayanarak:. Sen böyle bir şey yapabileceğini Can I use MarshalJSON to add arbitrary fields to a json encoding in golang?

(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

Thats bir yorum "olmak" (bu bir yorum olarak alanın büyük bir kaybı olsa bile) - ihraç edilmediğinden, serileştirmeden daha fazlasını önlemek için "json:" - "' a ihtiyacınız olmadığını unutmayın. –

+0

Bilgi için @NateFinch teşekkürler, mantıklı. Onu senin adına düzenliyorum. –

2

evet. bir yapı değil ama [] bayt türü json.Raw vardır. herhangi bir mareşal/belirsiz şekilde, onu yapıdan yönetebilirsiniz.

+0

Eğer json.Raw formatında '' "Extra2" eklemek için kodu sağlayabilir benim tamamen geçerli düzenleme gereken" ile mods tarafından reddedildi yana zor kısmı – Thellimist

2

haritası yaklaşım bunu yapmanın tek aklı başında yolu, her şey olduğu (gibi json.RawMessage alanlar zaten fazladan manevra adım gerektirecektir