简体   繁体   中英

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

I am creating a struct instance at runtime. The instance has been created successfully, but I can't unmarshal JSON into it.

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() .

Simply use the Value.Interface() method to obtain the pointer to your Test struct returned by reflect.New() , like this:

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. If you need the struct value, you may use type assertion, like this:

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

This prints:

{go}

Try the examples on the 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 . And when you unmarshal it, the json package looks into the reflect.Value struct which has no field Name , so it does nothing.

Instead, you should use reflect.Value.Interface() to turn it into an interface{} holding the concrete type.

Playground: https://play.golang.org/p/sW9mJd8fKMb

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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