interface{}型で受け取った引数を元の型に戻してjson.Unmarshalしたい
実現したいことは、json.Unmarshalを単純にラップした関数の作成なのですが、Unmarshalに渡す構造体はinterface{}型の引数として受け取りたいです。
しかし以下のように実現できていません。どのような方法があるでしょうか。
ステップ1:ベースとなるコード
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
}
func main() {
j := []byte(`{"name": "ando"}`)
var user User
if err := json.Unmarshal(j, &user); err != nil {
panic(err)
}
fmt.Printf("%#v", user)
//=> main.User{Name:"ando"}
}
ステップ2:interface{}型をそのまま渡して失敗
json.Unmarshalをラップした、unmarshal関数を作成。しかし、interface{}型をそのままUnmarshalに渡してしまったので、map型で返ってきてしまった。
func main() {
bs := []byte(`{"name": "ando"}`)
var user User
_, err := unmarshal(bs, user)
if err != nil {
panic(err)
}
}
func unmarshal(bs []byte, st interface{}) (interface{}, error) {
if err := json.Unmarshal(bs, &st); err != nil {
return nil, err
}
fmt.Printf("%#v\n", st)
//=> map[string]interface {}{"name":"ando"}
return st, nil
}
ステップ3:reflectパッケージで元の構造体に復元したつもりが失敗
初めてreflectパッケージを使い、見よう見まねでinterface{}型から元の構造体を復元したつもりが、エラーにはならないが正常にデコードされない。
import (
"encoding/json"
"fmt"
"reflect"
)
func unmarshal(bs []byte, st interface{}) (interface{}, error) {
// 元の構造体を復元しようとしたつもり
rv := reflect.New(reflect.TypeOf(st)).Elem()
if err := json.Unmarshal(bs, &rv); err != nil {
return nil, err
}
fmt.Printf("%#v\n", rv)
//=> main.User{Name:""} ※値が初期値のまま
return rv, nil
}