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

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

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

  1. v := typ.Elem()
  2. payload := reflect.New(v).Elem().Interface()
  3. eaa := json.NewDecoder(request.Body).Decode(payload)
  4. if e != nil {
  5. fmt.Println(eaa.Error())
  6. }
  7. fmt.Println(payload)
  8. fmt.Println(reflect.ValueOf(payload))
  9. return payload, nil

}

调用它的方式:

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

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

这有什么问题?

英文:
  1. func deserialize(request *http.Request,typ reflect.Type) (interface{}, *httpNet.HandlerError){
  2. data,e:=ioutil.ReadAll(request.Body)
  3. fmt.Println(string(data))
  4. if e !=nil{
  5. return nil,&httpNet.HandlerError{e,"could not read request",http.StatusBadRequest}
  6. }
  7. v:=typ.Elem()
  8. payload:=reflect.New(v).Elem().Interface()
  9. eaa:= json.NewDecoder(request.Body).Decode(payload)
  10. if e!=nil{
  11. fmt.Println(eaa.Error())
  12. }
  13. fmt.Println(payload)
  14. fmt.Println(reflect.ValueOf(payload)
  15. )
  16. return payload,nil
  17. }

to call it:

  1. 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

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

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

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

你应该将其简化为:

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

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

  1. if typ.Kind() == reflect.Ptr {
  2. typ = typ.Elem()
  3. }
  4. 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:

  1. 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:

  1. 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:

  1. if type.Kind() == reflect.Ptr {
  2. typ = typ.Elem()
  3. }
  4. 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:

确定