意図した構造体の代わりにマップを返す JSON アンマーシャリングの背後にある謎
Go での JSON アンマーシャリングは、インターフェイスと構造体を扱うときに課題を引き起こす可能性があります。開発者は、次のスニペットの場合のように、アンマーシャル プロセスで予期した構造体ではなくマップが生成される状況に遭遇することがあります。
<code class="go">import "encoding/json" import "fmt" import "reflect" func main() { type Ping struct { ID int `json:"id"` } var ping interface{} = Ping{} if err := json.Unmarshal([]byte(`{"id":42}`), &ping); err != nil { panic(err) } fmt.Println("Unexpected:", ping) // Result: map[id:42] }</code>
この動作の根本的な理由は、インターフェイスの抽象的な性質にあります。 JSON アンマーシャリングがインターフェイスで実行されると、結果は基になる型のフィールドを表すマップになります。上の例では、インターフェイス Ping は単一のキーと値のペア {"id":42} を持つマップを保持しています。
この問題を修正して目的の構造体を取得するには、ポインターを渡すことが重要です。特定の構造体タイプへ:
<code class="go">type Ping struct { ID int `json:"id"` } func main() { var ping Ping if err := json.Unmarshal([]byte(`{"id":42}`), &ping); err != nil { panic(err) } fmt.Println("Success:", ping) // Result: {42} }</code>
ポインターを Ping に渡すことにより、JSON アンマーシャル プロセスは、マップを作成するのではなく、構造体のインスタンスを作成し、そのフィールドにデータを設定するように指示されます。
また、具体的な構造体へのポインタが利用できない場合は、リフレクションを使用してポインタを動的に作成し、その後その値をインターフェイスに割り当てることができます:
<code class="go">import "reflect" func main() { var ping interface{} = Ping{} nptr := reflect.New(reflect.TypeOf(ping)) if err := json.Unmarshal([]byte(`{"id":42}`), nptr.Interface()); err != nil { panic(err) } ping = nptr.Elem().Interface() fmt.Println("Reflect-Based:", ping) // Result: {42} }</code>
以上がGo でインターフェイスを操作するときに JSON Unmarshal が構造体ではなくマップを返すのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。