解组 json 以反映结构(续)
Unmarshal json to reflected struct (continued)
我想编写一个 gin 中间件处理程序,它从 c.Request.FormValue("data")
获取数据,将其解组为一个结构(结构相当不同)并在上下文中设置一个变量(c.Set("Data",newP)
)。所以我搜索并写下了这个:
package middleware
import (
"reflect"
"fmt"
"github.com/gin-gonic/gin"
"encoding/json"
)
//https://semaphoreci.com/community/tutorials/test-driven-development-of-go-web-applications-with-gin
//https://github.com/gin-gonic/gin/issues/420
func Data(t reflect.Type) gin.HandlerFunc {
return func(c *gin.Context) {
//
//
//t := reflect.TypeOf(orig)
v := reflect.New(t.Elem())
// reflected pointer
newP := v.Interface()
data:=c.Request.FormValue("data")
fmt.Printf("%s data:%s\n",c.Request.URL.Path,data)
if err:=json.Unmarshal([]byte(data),newP); err!=nil{
fmt.Printf("%s data unmarshall %s, data(in quotes):\"%s\"",c.Request.URL.Path,err,data)
c.Abort()
return
}
ustr, _:=json.Marshal(newP)
fmt.Printf("%s unmarshalled:%s\n",c.Request.URL.Path,ustr)
c.Set("Data",newP)
c.Next()
}
}
我是这样使用它的:
func InitHandle(R *gin.Engine) {
Plan := R.Group("/Plan")
Plan.POST("/clickCreate",middleware.Data(reflect.TypeOf(new(tls.PlanTabel))), clickCreatePlanHandle)
}
和
var data = *(c.MustGet("Data").(*tls.PlanTabel))
又重又丑。我想
middleware.Data(tls.PlanTabel{})
和
var data = c.MustGet("Data").(tls.PlanTabel)
换句话说,忽略杜松子酒,我想要一个吃掉i interface{}
和returns函数的闭包(data string) (o interface{})
func Data(i interface{}) (func (string) (interface{})) {
//some reflect magic goes here
//extract the structure type from interface{} :
//gets a reflect type pointer to it, like
//t := reflect.TypeOf(orig)
return func(data string) (o interface{}) {
//new reflected structure (pointer?)
v := reflect.New(t.Elem())
//interface to it
newP := v.Interface()
//unmarshal
json.Unmarshal([]byte(data),newP);
//get the structure from the pointer back
//returns interface to the structure
//reflect magic ends
}
}
问题中的代码很接近。
尝试以下功能。结果函数 returns 的类型与 i
的类型相同:
func Data(i interface{}) func(string) (interface{}, error) {
return func(data string) (interface{}, error) {
v := reflect.New(reflect.TypeOf(i))
err := json.Unmarshal([]byte(data), v.Interface())
return v.Elem().Interface(), err
}
}
使用示例:
type Test struct {
A string
B string
}
f := Data((*Test)(nil))
v, err := f(`{"A": "hello", "B": "world"}`)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", v) // v is a *Test
f = Data("")
v, err = f(`"Hello"`)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", v) // v is a string
如果你想 return 一个结构值,然后将一个结构值作为参数传递给 Data:
f = Data(Test{})
v, err = f(`{"A": "hello", "B": "world"}`)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", v) // v is a Test
我想编写一个 gin 中间件处理程序,它从 c.Request.FormValue("data")
获取数据,将其解组为一个结构(结构相当不同)并在上下文中设置一个变量(c.Set("Data",newP)
)。所以我搜索并写下了这个:
package middleware
import (
"reflect"
"fmt"
"github.com/gin-gonic/gin"
"encoding/json"
)
//https://semaphoreci.com/community/tutorials/test-driven-development-of-go-web-applications-with-gin
//https://github.com/gin-gonic/gin/issues/420
func Data(t reflect.Type) gin.HandlerFunc {
return func(c *gin.Context) {
//
//
//t := reflect.TypeOf(orig)
v := reflect.New(t.Elem())
// reflected pointer
newP := v.Interface()
data:=c.Request.FormValue("data")
fmt.Printf("%s data:%s\n",c.Request.URL.Path,data)
if err:=json.Unmarshal([]byte(data),newP); err!=nil{
fmt.Printf("%s data unmarshall %s, data(in quotes):\"%s\"",c.Request.URL.Path,err,data)
c.Abort()
return
}
ustr, _:=json.Marshal(newP)
fmt.Printf("%s unmarshalled:%s\n",c.Request.URL.Path,ustr)
c.Set("Data",newP)
c.Next()
}
}
我是这样使用它的:
func InitHandle(R *gin.Engine) {
Plan := R.Group("/Plan")
Plan.POST("/clickCreate",middleware.Data(reflect.TypeOf(new(tls.PlanTabel))), clickCreatePlanHandle)
}
和
var data = *(c.MustGet("Data").(*tls.PlanTabel))
又重又丑。我想
middleware.Data(tls.PlanTabel{})
和
var data = c.MustGet("Data").(tls.PlanTabel)
换句话说,忽略杜松子酒,我想要一个吃掉i interface{}
和returns函数的闭包(data string) (o interface{})
func Data(i interface{}) (func (string) (interface{})) {
//some reflect magic goes here
//extract the structure type from interface{} :
//gets a reflect type pointer to it, like
//t := reflect.TypeOf(orig)
return func(data string) (o interface{}) {
//new reflected structure (pointer?)
v := reflect.New(t.Elem())
//interface to it
newP := v.Interface()
//unmarshal
json.Unmarshal([]byte(data),newP);
//get the structure from the pointer back
//returns interface to the structure
//reflect magic ends
}
}
问题中的代码很接近。
尝试以下功能。结果函数 returns 的类型与 i
的类型相同:
func Data(i interface{}) func(string) (interface{}, error) {
return func(data string) (interface{}, error) {
v := reflect.New(reflect.TypeOf(i))
err := json.Unmarshal([]byte(data), v.Interface())
return v.Elem().Interface(), err
}
}
使用示例:
type Test struct {
A string
B string
}
f := Data((*Test)(nil))
v, err := f(`{"A": "hello", "B": "world"}`)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", v) // v is a *Test
f = Data("")
v, err = f(`"Hello"`)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", v) // v is a string
如果你想 return 一个结构值,然后将一个结构值作为参数传递给 Data:
f = Data(Test{})
v, err = f(`{"A": "hello", "B": "world"}`)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", v) // v is a Test