2017-03-02 9 views
3

私は、次のしている:構造体のjsonタグを動的に変更するにはどうすればよいですか?

package main 

import (
    "encoding/json" 
    "fmt" 
    "os" 
    "reflect" 
) 

type User struct { 
    ID int64 `json:"id"` 
    Name string `json:"first"` // want to change this to `json:"name"` 
    tag string `json:"-"` 
    Another 
} 

type Another struct { 
    Address string `json:"address"` 
} 

func (u *User) MarshalJSON() ([]byte, error) { 
    value := reflect.ValueOf(*u) 
    for i := 0; i < value.NumField(); i++ { 
     tag := value.Type().Field(i).Tag.Get("json") 
     field := value.Field(i) 
     fmt.Println(tag, field) 
    } 
    return json.Marshal(u) 
} 

func main() { 
     anoth := Another{"123 Jennings Street"} 
    _ = json.NewEncoder(os.Stdout).Encode(
     &User{1, "Ken Jennings", "name", 
      anoth}, 
    ) 
} 

私はJSONエンコードに構造体をしようとしていますが、私は、私はJSONのキーを変更する必要があります前に...例えば、最終的なJSONは次のようになります。

{"id": 1, "name": "Ken Jennings", "address": "123 Jennings Street"} 

value.Type()。Field(i).Tag.Get( "json")のメソッドに気付きましたが、セッターメソッドはありません。どうして?希望のjson出力を得るにはどうすればいいですか?

また、組み込みのstruct anotherを含む、すべてのフィールドをどのように反復処理しますか?

https://play.golang.org/p/Qi8Jq_4W0t

+0

タグは設定可能なフィールドではなく、タイプの一部です。 – JimB

+0

これにはクリーンな解決策がないかもしれません。汚れたものの1つがコード生成を使用しています。 – ymonad

+3

json.Marshaler(https://golang.org/pkg/encoding/json/#Marshaler)インターフェイスを実装して、構造タグを無視するか、任意のフィールドに任意の名前を付けることができます。 – elithrar

答えて

1

それは場しのぎだが、あなたは別で構造体をラップし、エンコーディングのための新しいものを使用することができれば、あなたはできる:

  1. それをデコード
  2. 、オリジナルの構造体をエンコードinterface{}に地図を入手する
  3. マップキーを交換する
  4. 次に地図をエンコードして返信する
  5. したがって

:遊び場で

type MyUser struct { 
    U User 
} 

func (u MyUser) MarshalJSON() ([]byte, error) { 
    // encode the original 
    m, _ := json.Marshal(u.U) 

    // decode it back to get a map 
    var a interface{} 
    json.Unmarshal(m, &a) 
    b := a.(map[string]interface{}) 

    // Replace the map key 
    b["name"] = b["first"] 
    delete(b, "first") 

    // Return encoding of the map 
    return json.Marshal(b) 
} 

https://play.golang.org/p/TabSga4i17

3

ゴー1.8では、あなたが簡単な解決策を使用することができます。このコード:

func main() { 
    anoth := Another{"123 Jennings Street"} 

    _ = json.NewEncoder(os.Stdout).Encode(
     &User{1, "Ken Jennings", "name", 
      anoth}, 
    ) 
} 

type User struct { 
    ID int64 `json:"id"` 
    Name string `json:"first"` // want to change this to `json:"name"` 
    tag string `json:"-"` 
    Another 
} 

type Another struct { 
    Address string `json:"address"` 
} 

func (u *User) MarshalJSON() ([]byte, error) { 
    type alias struct { 
     ID int64 `json:"id"` 
     Name string `json:"name"` 
     tag string `json:"-"` 
     Another 
    } 
    var a alias = alias(*u) 
    return json.Marshal(&a) 
} 

が私たちを与える:ゴー1.8で使用すると、同じ構造が、互いに異なるタグを持つ構造体を割り当てることができるという事実によって可能になっ

{"id":1,"name":"Ken Jennings","address":"123 Jennings Street"} 

このソリューション。 aliasのタイプは、Userと同じフィールドがありますが、異なるタグを使用しています。

+0

上記のコメントを参照してください。 –

関連する問題