未知の構造体の JSON 出力を動的に強化する
はじめに
Go では、既知の構造体を匿名フィールドとして埋め込むことによる JSON 出力。ただし、この手法は特定のタイプでのみ機能します。この記事では、この機能を未知の構造体またはインターフェイスに拡張する方法について説明します。
例
次の例を考えてみましょう。
type example interface{} type Data struct { Name string } func printInterface(val interface{}) { example1 := struct { example Extra string }{ example: val, Extra: "text", } json.NewEncoder(os.Stdout).Encode(example1) } func main() { d := Data{Name: "name"} printInterface(&d) }
このコードは次の JSON を出力します。 :
{"example":{"Name":"name"},"Extra":"text"}
「名前」フィールドが不要な「例」内にラップされていることに注目してください。 object.
解決策 1: リフレクションを使用した動的型の生成
「サンプル」オブジェクトを回避するには、実行時に動的型を生成する必要があります。リフレクションを使用して、未知のインターフェイスを埋め込み、追加の「Extra」フィールドを含む構造体型を作成できます。
func printInterface(val interface{}) { t2 := reflect.StructOf([]reflect.StructField{ { Name: "X", Anonymous: true, Type: reflect.TypeOf(val), }, { Name: "Extra", Type: reflect.TypeOf(""), }, }) v2 := reflect.New(t2).Elem() v2.Field(0).Set(reflect.ValueOf(val)) v2.FieldByName("Extra").SetString("text") json.NewEncoder(os.Stdout).Encode(v2.Interface()) }
この変更により、出力は次のようになります。
{"Name":"name","Extra":"text"}
解決策 2: マーシャリングとアンマーシャリング
別のアプローチは、インターフェイスをマーシャリングすることです。それをマップにアンマーシャリングし、追加のフィールドを追加して、再度マーシャリングします。
func printInterface(val interface{}) error { data, err := json.Marshal(val) if err != nil { return err } v2 := map[string]interface{}{} if err := json.Unmarshal(data, &v2); err != nil { return err } v2["Extra"] = "text" return json.NewEncoder(os.Stdout).Encode(v2) }
このメソッドは、動的型アプローチと同じ出力を生成します。
結論
ここで紹介する両方のソリューションでは、未知の構造体またはインターフェイスの任意のフィールドを使用して JSON 出力を拡張できます。リフレクションベースのアプローチはタイプセーフなソリューションを提供しますが、マーシャリングおよびアンマーシャリング技術はより単純ですが、速度が低下する可能性があります。方法の選択は、アプリケーションの特定の要件によって異なります。
以上が不明な Go 構造体から JSON 出力にフィールドを動的に追加する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。