动态创建某种类型的结构并将JSON解组到该实例中

时间:2018-06-18 07:40:01

标签: json pointers go struct reflection

我正在运行时创建一个struct实例。该实例已成功创建,但我无法将JSON解组到其中。

type Test struct {
    Name string `json:"name,omitempty"`
}

func create(a interface{}) {
    aType := reflect.TypeOf(a).Elem()
    elType := aType.Elem()

    f := reflect.Indirect(reflect.New(elType))

    b := []byte(`{"name": "go"}`)

    err := json.Unmarshal(b, &f)
    fmt.Println(err, f)
}

func main() {
    l := []Test{}
    create(&l)
}

3 个答案:

答案 0 :(得分:3)

reflect.Indirect()会返回reflect.Value类型的值,您应该将指向Test(类型为*Test)的指针传递给json.Unmarshal()

只需使用Value.Interface()方法获取指向reflect.New()返回的Test结构的指针,如下所示:

f := reflect.New(elType).Interface()
b := []byte(`{"name": "go"}`)
err := json.Unmarshal(b, f)

使用它可以工作,输出将是:

<nil> &{go}

请注意,f将为interface{}类型,并保留*Test指针值。如果需要struct值,可以使用类型断言,如下所示:

t := *f.(*Test)
fmt.Println(t)

打印:

{go}

尝试Go Playground上的示例。

答案 1 :(得分:3)

我认为您不需要使用反射,而是可以执行以下操作:

type Test struct {
    Name string `json:"name,omitempty"`
}

func create(a interface{}) {
    b := []byte(`[{"name": "go"}]`)

    err := json.Unmarshal(b, &a)
    fmt.Println(err, a)
}

func main() {
    l := []Test{}
    create(&l)
}

答案 2 :(得分:2)

代码reflect.Indirect(reflect.New(elType)) 返回reflect.Value而不是elType的具体值。当你解组它时,json包会查看没有字段reflect.Value的{​​{1}}结构,所以它什么都不做。

相反,您应该使用Name将其转换为保留具体类型的reflect.Value.Interface()

游乐场:https://play.golang.org/p/sW9mJd8fKMb