mirror of
https://github.com/zeromicro/go-zero.git
synced 2025-02-03 00:38:40 +08:00
fix marshal ptr in httpc (#1789)
* fix marshal ptr in httpc * add more tests * add more tests * add more tests * fix issue on options and optional both provided
This commit is contained in:
parent
ee88abce14
commit
cb4fcf2c6c
@ -16,7 +16,13 @@ const (
|
|||||||
func Marshal(val interface{}) (map[string]map[string]interface{}, error) {
|
func Marshal(val interface{}) (map[string]map[string]interface{}, error) {
|
||||||
ret := make(map[string]map[string]interface{})
|
ret := make(map[string]map[string]interface{})
|
||||||
tp := reflect.TypeOf(val)
|
tp := reflect.TypeOf(val)
|
||||||
|
if tp.Kind() == reflect.Ptr {
|
||||||
|
tp = tp.Elem()
|
||||||
|
}
|
||||||
rv := reflect.ValueOf(val)
|
rv := reflect.ValueOf(val)
|
||||||
|
if rv.Kind() == reflect.Ptr {
|
||||||
|
rv = rv.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < tp.NumField(); i++ {
|
for i := 0; i < tp.NumField(); i++ {
|
||||||
field := tp.Field(i)
|
field := tp.Field(i)
|
||||||
@ -87,6 +93,10 @@ func validate(field reflect.StructField, value reflect.Value, opt *fieldOptions)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opt.Optional && value.IsZero() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if len(opt.Options) > 0 {
|
if len(opt.Options) > 0 {
|
||||||
if err := validateOptions(value, opt); err != nil {
|
if err := validateOptions(value, opt); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -27,6 +27,27 @@ func TestMarshal(t *testing.T) {
|
|||||||
assert.True(t, m[emptyTag]["Anonymous"].(bool))
|
assert.True(t, m[emptyTag]["Anonymous"].(bool))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMarshal_Ptr(t *testing.T) {
|
||||||
|
v := &struct {
|
||||||
|
Name string `path:"name"`
|
||||||
|
Address string `json:"address,options=[beijing,shanghai]"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
Anonymous bool
|
||||||
|
}{
|
||||||
|
Name: "kevin",
|
||||||
|
Address: "shanghai",
|
||||||
|
Age: 20,
|
||||||
|
Anonymous: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := Marshal(v)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "kevin", m["path"]["name"])
|
||||||
|
assert.Equal(t, "shanghai", m["json"]["address"])
|
||||||
|
assert.Equal(t, 20, m["json"]["age"].(int))
|
||||||
|
assert.True(t, m[emptyTag]["Anonymous"].(bool))
|
||||||
|
}
|
||||||
|
|
||||||
func TestMarshal_OptionalPtr(t *testing.T) {
|
func TestMarshal_OptionalPtr(t *testing.T) {
|
||||||
var val = 1
|
var val = 1
|
||||||
v := struct {
|
v := struct {
|
||||||
@ -71,6 +92,26 @@ func TestMarshal_NotInOptions(t *testing.T) {
|
|||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMarshal_NotInOptionsOptional(t *testing.T) {
|
||||||
|
v := struct {
|
||||||
|
Name string `json:"name,options=[a,b],optional"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
_, err := Marshal(v)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshal_NotInOptionsOptionalWrongValue(t *testing.T) {
|
||||||
|
v := struct {
|
||||||
|
Name string `json:"name,options=[a,b],optional"`
|
||||||
|
}{
|
||||||
|
Name: "kevin",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := Marshal(v)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestMarshal_Nested(t *testing.T) {
|
func TestMarshal_Nested(t *testing.T) {
|
||||||
type address struct {
|
type address struct {
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
|
@ -987,6 +987,43 @@ func TestUnmarshalWithStringOptionsCorrect(t *testing.T) {
|
|||||||
ast.Equal("2", in.Correct)
|
ast.Equal("2", in.Correct)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalOptionsOptional(t *testing.T) {
|
||||||
|
type inner struct {
|
||||||
|
Value string `key:"value,options=first|second,optional"`
|
||||||
|
OptionalValue string `key:"optional_value,options=first|second,optional"`
|
||||||
|
Foo string `key:"foo,options=[bar,baz]"`
|
||||||
|
Correct string `key:"correct,options=1|2"`
|
||||||
|
}
|
||||||
|
m := map[string]interface{}{
|
||||||
|
"value": "first",
|
||||||
|
"foo": "bar",
|
||||||
|
"correct": "2",
|
||||||
|
}
|
||||||
|
|
||||||
|
var in inner
|
||||||
|
ast := assert.New(t)
|
||||||
|
ast.Nil(UnmarshalKey(m, &in))
|
||||||
|
ast.Equal("first", in.Value)
|
||||||
|
ast.Equal("", in.OptionalValue)
|
||||||
|
ast.Equal("bar", in.Foo)
|
||||||
|
ast.Equal("2", in.Correct)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalOptionsOptionalWrongValue(t *testing.T) {
|
||||||
|
type inner struct {
|
||||||
|
Value string `key:"value,options=first|second,optional"`
|
||||||
|
OptionalValue string `key:"optional_value,options=first|second,optional"`
|
||||||
|
WrongValue string `key:"wrong_value,options=first|second,optional"`
|
||||||
|
}
|
||||||
|
m := map[string]interface{}{
|
||||||
|
"value": "first",
|
||||||
|
"wrong_value": "third",
|
||||||
|
}
|
||||||
|
|
||||||
|
var in inner
|
||||||
|
assert.NotNil(t, UnmarshalKey(m, &in))
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnmarshalStringOptionsWithStringOptionsNotString(t *testing.T) {
|
func TestUnmarshalStringOptionsWithStringOptionsNotString(t *testing.T) {
|
||||||
type inner struct {
|
type inner struct {
|
||||||
Value string `key:"value,options=first|second"`
|
Value string `key:"value,options=first|second"`
|
||||||
|
@ -73,6 +73,40 @@ func TestDo(t *testing.T) {
|
|||||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDo_Ptr(t *testing.T) {
|
||||||
|
type Data struct {
|
||||||
|
Key string `path:"key"`
|
||||||
|
Value int `form:"value"`
|
||||||
|
Header string `header:"X-Header"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
rt := router.NewRouter()
|
||||||
|
err := rt.Handle(http.MethodPost, "/nodes/:key",
|
||||||
|
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req Data
|
||||||
|
assert.Nil(t, httpx.Parse(r, &req))
|
||||||
|
assert.Equal(t, "foo", req.Key)
|
||||||
|
assert.Equal(t, 10, req.Value)
|
||||||
|
assert.Equal(t, "my-header", req.Header)
|
||||||
|
assert.Equal(t, "my body", req.Body)
|
||||||
|
}))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
svr := httptest.NewServer(http.HandlerFunc(rt.ServeHTTP))
|
||||||
|
defer svr.Close()
|
||||||
|
|
||||||
|
data := &Data{
|
||||||
|
Key: "foo",
|
||||||
|
Value: 10,
|
||||||
|
Header: "my-header",
|
||||||
|
Body: "my body",
|
||||||
|
}
|
||||||
|
resp, err := Do(context.Background(), http.MethodPost, svr.URL+"/nodes/:key", data)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDo_BadRequest(t *testing.T) {
|
func TestDo_BadRequest(t *testing.T) {
|
||||||
_, err := Do(context.Background(), http.MethodPost, ":/nodes/:key", nil)
|
_, err := Do(context.Background(), http.MethodPost, ":/nodes/:key", nil)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
Loading…
Reference in New Issue
Block a user