将JSON转换为Golang中的结构体可以使用反射(reflection)来实现。

huangapple go评论85阅读模式
英文:

Convert json to struct using reflection in golang

问题

func deserialize(request *http.Request, typ reflect.Type) (interface{}, *httpNet.HandlerError) {
data, e := ioutil.ReadAll(request.Body)
fmt.Println(string(data))
if e != nil {
return nil, &httpNet.HandlerError{e, "无法读取请求", http.StatusBadRequest}
}

v := typ.Elem()
payload := reflect.New(v).Elem().Interface()

eaa := json.NewDecoder(request.Body).Decode(payload)

if e != nil {
    fmt.Println(eaa.Error())
}
fmt.Println(payload)
fmt.Println(reflect.ValueOf(payload))
return payload, nil

}

调用它的方式:

r, _ := deserialize(request, reflect.TypeOf(&testData{}))

在我看来,它没有抛出错误,看起来完全有效,但结果是一个期望类型的空结构。

这有什么问题?

英文:
func deserialize(request *http.Request,typ reflect.Type) (interface{}, *httpNet.HandlerError){
	
	data,e:=ioutil.ReadAll(request.Body)
	fmt.Println(string(data))
	if e !=nil{
		return nil,&httpNet.HandlerError{e,"could not read request",http.StatusBadRequest}
	}

	v:=typ.Elem()
	payload:=reflect.New(v).Elem().Interface()

	eaa:= json.NewDecoder(request.Body).Decode(payload)
	
	if e!=nil{
		fmt.Println(eaa.Error())
	}
	fmt.Println(payload)
	fmt.Println(reflect.ValueOf(payload)
		)
	return payload,nil

}

to call it:

r,_:= deserialize(request,reflect.TypeOf(&testData{}))

It does not throw errors and looks completely valid operation to me , but the result is an empty structure of expecting type.

Whats the problem with that?

答案1

得分: 4

问题在于你传递了一个非指针类型的实例:

payload := reflect.New(v).Elem().Interface()

这意味着“分配一个指向该类型的新指针,然后取其值,并将其提取为interface{}”。

你应该将其简化为:

payload := reflect.New(v).Interface()

另外,你传递指针类型的类型,然后提取其Elem(),再分配一个指针,这也是多余的。可以像这样做:

if typ.Kind() == reflect.Ptr {
   typ = typ.Elem()
}

payload := reflect.New(typ).Interface()

然后你可以将指针和非指针都传递给该函数。

编辑:工作示例:http://play.golang.org/p/TPafxcpIU5

英文:

The problem is that you are passing a non pointer instance of the type:

payload:=reflect.New(v).Elem().Interface()

Means "allocate a new pointer to the type, then take the value of it, and extract it as interface{}.

You should just keep it at:

payload:=reflect.New(v).Interface()

BTW It's also redundant that you are passing the type of a pointer, extracting its Elem(), then allocating a pointer. Do something like this:

if type.Kind() == reflect.Ptr {
   typ = typ.Elem()
}

payload := reflect.New(typ).Interface()

then you can pass both pointers and non pointers to the function.

Edit: Working playground example: http://play.golang.org/p/TPafxcpIU5

huangapple
  • 本文由 发表于 2015年6月14日 18:25:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/30828258.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定