简体   繁体   English

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

[英]Dynamically create struct of some type and unmarshal JSON into that instance

I am creating a struct instance at runtime. 我在运行时创建一个struct实例。 The instance has been created successfully, but I can't unmarshal JSON into it. 该实例已成功创建,但我无法将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)
}

reflect.Indirect() returns you a value of type reflect.Value , and you should pass a pointer to Test (which is of type *Test ) to json.Unmarshal() . reflect.Indirect()返回一个reflect.Value类型的值,你应该将指向Test (其类型为*Test )的指针传递给json.Unmarshal()

Simply use the Value.Interface() method to obtain the pointer to your Test struct returned by reflect.New() , like this: 只需使用Value.Interface()方法获取指向reflect.New()返回的Test结构的指针,如下所示:

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

With this it works, and output will be: 有了这个工作,输出将是:

<nil> &{go}

Note that f will be of interface{} type, holding the *Test pointer value. 注意f将是interface{}类型,保持*Test指针值。 If you need the struct value, you may use type assertion, like this: 如果需要struct值,可以使用类型断言,如下所示:

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

This prints: 这打印:

{go}

Try the examples on the Go Playground . 试试Go Playground上的例子。

I don't think you need to use reflect, instead you can do the following: 我认为您不需要使用反射,而是可以执行以下操作:

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)
}

The code reflect.Indirect(reflect.New(elType)) returns a reflect.Value instead of a concrete value of elType . 代码reflect.Indirect(reflect.New(elType))返回一个reflect.Value代替的具体值elType And when you unmarshal it, the json package looks into the reflect.Value struct which has no field Name , so it does nothing. 当你解组它时,json包会查看没有字段Namereflect.Value结构,所以它什么都不做。

Instead, you should use reflect.Value.Interface() to turn it into an interface{} holding the concrete type. 相反,您应该使用reflect.Value.Interface()将其转换为保持具体类型的interface{}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM