[英]Unmarshal json to reflected struct
Is it possible to unmarshal JSON into a struct made from reflection without hardcoding the original type?是否可以在不硬编码原始类型的情况下将 JSON 解组为由反射制成的结构?
package main
import (
"fmt"
"encoding/json"
"reflect"
)
type Employee struct {
Firstname string `json:"firstname"`
}
func main() {
//Original struct
orig := new(Employee)
t := reflect.TypeOf(orig)
v := reflect.New(t.Elem())
//Reflected struct
new := v.Elem().Interface().(Employee)
// Unmarshal to reflected struct
json.Unmarshal([]byte("{\"firstname\": \"bender\"}"), &new)
fmt.Printf("%+v\n", new)
}
I used a cast to Employee
in this example.在此示例中,我使用了对
Employee
的强制转换。 But what if i don't know the type?但是如果我不知道类型怎么办?
When i just use v
for the unmarhaling the struct will be zeroed.当我只使用
v
进行解组时,结构将被清零。
json.Unmarshal([]byte("{\"firstname\": \"bender\"}"), v)
When I omit the cast I get a map.当我省略演员表时,我会得到一张地图。 which is understandable
这是可以理解的
json.Unmarshal([]byte("{\"firstname\": \"bender\"}"), v.Elem().Interface())
The problem here is that if you omit the type assertion here: 这里的问题是,如果你在这里省略类型断言:
new := v.Elem().Interface()
The new
is inferred to have a interface{}
type. 推断
new
具有interface{}
类型。
Then when you take the address to unmarshal, the type of &new
is *interface{}
(pointer to interface{}) and unmarshal does not work as you expect. 然后当你取消地址解组时,
&new
的类型是*interface{}
(指向接口{}的指针)和unmarshal不能按预期工作。
You can avoid the type assertion if instead of getting the Elem()
you work directly with the pointer reference. 如果不是让
Elem()
直接使用指针引用,则可以避免使用类型断言。
func main() {
//Original struct
orig := new(Employee)
t := reflect.TypeOf(orig)
v := reflect.New(t.Elem())
// reflected pointer
newP := v.Interface()
// Unmarshal to reflected struct pointer
json.Unmarshal([]byte("{\"firstname\": \"bender\"}"), newP)
fmt.Printf("%+v\n", newP)
}
Playground: https://play.golang.org/p/lTBU-1PqM4 游乐场: https : //play.golang.org/p/lTBU-1PqM4
If you don't know the type at all, you can Unmarshal the JSON string into an interface{}. 如果您根本不知道类型,则可以将JSON字符串解组为接口{}。 If you then need to work with the Unmarshaled data, you can convert it to the desired type.
如果您需要使用Unmarshaled数据,则可以将其转换为所需类型。
Here's an example: 这是一个例子:
package main
import (
"encoding/json"
"fmt"
"reflect"
"unsafe"
)
type Employee struct {
Firstname string `json:"firstName"`
}
func deserialize(jsonData string) interface{} {
var obj interface{}
if err := json.Unmarshal([]byte(jsonData), &obj); err != nil {
panic(err)
}
return obj
}
func NewEmployee(objData map[string]interface{}) *Employee {
s := (*Employee)(nil)
t := reflect.TypeOf(s).Elem()
employeePtr := reflect.New(t)
employee := (*Employee)(unsafe.Pointer(employeePtr.Pointer()))
employee.Firstname = objData["firstName"].(string)
return employee
}
func main() {
jsonData := "{\"firstName\": \"John\"}"
obj := deserialize(jsonData)
objData := obj.(map[string]interface{})
employee := NewEmployee(objData)
fmt.Printf("%s\n", employee.Firstname)
}
You can check it on the Go Playground . 您可以在Go Playground上查看 。
// https://github.com/xiaojun207/go-base-utils/blob/master/utils/Clone.go
func NewInterface(typ reflect.Type, data []byte) interface{} {
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
dst := reflect.New(typ).Elem()
json.Unmarshal(data, dst.Addr().Interface())
return dst.Addr().Interface()
}else {
dst := reflect.New(typ).Elem()
json.Unmarshal(data, dst.Addr().Interface())
return dst.Interface()
}
}
type Employee struct {
Firstname string `json:"firstname"`
}
func main() {
data := "{\"firstName\": \"John\"}"
obj := NewInterface(reflect.TypeOf(Employee{}), []byte(data))
fmt.Println("Employee:", obj)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.