是否可以将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)
}
在这个例子中,我使用了强制转换为Employee
。但如果我不知道这种类型怎么办?
当我只使用v
进行解组时,结构将被清零。
json.Unmarshal([]byte("{\"firstname\": \"bender\"}"), v)
当我省略演员表时,我会得到一张地图。这是可以理解的
json.Unmarshal([]byte("{\"firstname\": \"bender\"}"), v.Elem().Interface())
答案 0 :(得分:7)
这里的问题是,如果省略这里的类型断言:
new := v.Elem().Interface()
推断new
具有interface{}
类型。
然后当你取消地址解组时,&new
的类型是*interface{}
(指向接口{}的指针)和unmarshal不能按预期工作。
您可以避免使用类型断言,而不是让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)
}
答案 1 :(得分:0)
如果您根本不知道类型,可以将JSON字符串解组为接口{}。如果您需要使用Unmarshaled数据,则可以将其转换为所需类型。
以下是一个例子:
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)
}
您可以在Go Playground上查看。