diff --git a/binding/binding_test.go b/binding/binding_test.go index 9af4f88a..f18d38ed 100644 --- a/binding/binding_test.go +++ b/binding/binding_test.go @@ -18,9 +18,11 @@ import ( "testing" "time" - "github.com/gin-gonic/gin/testdata/protoexample" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "google.golang.org/protobuf/proto" + + "github.com/gin-gonic/gin/testdata/protoexample" ) type appkey struct { @@ -796,12 +798,15 @@ func TestUriBinding(t *testing.T) { assert.Equal(t, "uri", b.Name()) type Tag struct { - Name string `uri:"name"` + ID uuid.NullUUID `uri:"id"` + Name string `uri:"name"` } var tag Tag m := make(map[string][]string) + m["id"] = []string{"5b620cc3-a5eb-4515-8fc7-4686d5cadfa9"} m["name"] = []string{"thinkerou"} assert.NoError(t, b.BindUri(m, &tag)) + assert.Equal(t, uuid.NullUUID{Valid: true, UUID: uuid.MustParse("5b620cc3-a5eb-4515-8fc7-4686d5cadfa9")}, tag.ID) assert.Equal(t, "thinkerou", tag.Name) type NotSupportStruct struct { diff --git a/binding/form_mapping.go b/binding/form_mapping.go index 540bbbb8..3526c04e 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -236,9 +236,9 @@ func setWithProperType(val string, value reflect.Value, field reflect.StructFiel case time.Time: return setTimeField(val, field, value) } - return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) + return json.Unmarshal(completeJSONBytes(bytesconv.StringToBytes(val)), value.Addr().Interface()) case reflect.Map: - return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) + return json.Unmarshal(completeJSONBytes(bytesconv.StringToBytes(val)), value.Addr().Interface()) default: return errUnknownType } @@ -401,3 +401,15 @@ func setFormMap(ptr any, form map[string][]string) error { return nil } + +func completeJSONBytes(bs []byte) []byte { + if len(bs) == 0 || + bs[0] == '"' && bs[len(bs)-1] == '"' { + return bs + } + var cbs = make([]byte, len(bs)+2) + cbs[0] = '"' + copy(cbs[1:], bs) + cbs[len(cbs)-1] = '"' + return cbs +} diff --git a/binding/form_mapping_test.go b/binding/form_mapping_test.go index 93d6a92f..8d0982fa 100644 --- a/binding/form_mapping_test.go +++ b/binding/form_mapping_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/google/uuid" "github.com/stretchr/testify/assert" ) @@ -136,6 +137,31 @@ func TestMappingURI(t *testing.T) { assert.Equal(t, 6, s.F) } +func TestMappingURICompositeTypes(t *testing.T) { + for _, tt := range []struct { + name string + value any + uri string + expect any + }{ + {"uuid", struct{ F uuid.NullUUID }{}, "5b620cc3-a5eb-4515-8fc7-4686d5cadfa9", uuid.NullUUID{Valid: true, UUID: uuid.MustParse("5b620cc3-a5eb-4515-8fc7-4686d5cadfa9")}}, + } { + tp := reflect.TypeOf(tt.value) + testName := tt.name + ":" + tp.Field(0).Type.String() + + val := reflect.New(reflect.TypeOf(tt.value)) + val.Elem().Set(reflect.ValueOf(tt.value)) + + field := val.Elem().Type().Field(0) + + _, err := mapping(val, emptyField, formSource{field.Name: {tt.uri}}, "uri") + assert.NoError(t, err, testName) + + actual := val.Elem().Field(0).Interface() + assert.Equal(t, tt.expect, actual, testName) + } +} + func TestMappingForm(t *testing.T) { var s struct { F int `form:"field"` diff --git a/go.mod b/go.mod index 200a4403..2616ccd1 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/gin-contrib/sse v0.1.0 github.com/go-playground/validator/v10 v10.11.1 github.com/goccy/go-json v0.9.11 + github.com/google/uuid v1.3.0 github.com/json-iterator/go v1.1.12 github.com/mattn/go-isatty v0.0.16 github.com/pelletier/go-toml/v2 v2.0.6 diff --git a/go.sum b/go.sum index 574e4a9a..368099a7 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=