diff --git a/binding/form_mapping.go b/binding/form_mapping.go index 33389b28..fc1f3f39 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -182,6 +182,26 @@ func trySetCustom(val string, value reflect.Value) (isSet bool, err error) { return false, nil } +// trySetArrayOfCustom works as trySetCustom but for an array of custom values +// If the value implements the BindUnmarshaler interface, it will be used to set the values, +// we will return `true` to skip the default value setting. +func trySetArrayOfCustom(vals []string, arrayValue reflect.Value) (isSet bool, err error) { + switch arrayValue.Index(0).Addr().Interface().(type) { + case BindUnmarshaler: + for i, s := range vals { + { + err := arrayValue.Index(i).Addr().Interface().(BindUnmarshaler).UnmarshalParam(s) + if err != nil { + return true, err + } + } + } + return true, nil + default: + return false, nil + } +} + func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSet bool, err error) { vs, ok := form[tagValue] if !ok && !opt.isDefaultExists { @@ -379,6 +399,11 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val } func setArray(vals []string, value reflect.Value, field reflect.StructField) error { + ok, err := trySetArrayOfCustom(vals, value) + if ok { + return err + } + for i, s := range vals { err := setWithProperType(s, value.Index(i), field) if err != nil { diff --git a/binding/form_mapping_test.go b/binding/form_mapping_test.go index afd51f9d..16b01ec4 100644 --- a/binding/form_mapping_test.go +++ b/binding/form_mapping_test.go @@ -509,3 +509,23 @@ func TestMappingCustomArrayForm(t *testing.T) { expected, _ := convertTo(val) assert.EqualValues(t, expected, s.FileData) } + +func TestMappingSliceWithCustomUnmarshal(t *testing.T) { + var s struct { + HexSlice []customUnmarshalParamHex `form:"hex_slice"` + } + err := mappingByPtr(&s, formSource{"hex_slice": {`f5`, `f6`}}, "form") + assert.NoError(t, err) + + assert.EqualValues(t, []customUnmarshalParamHex{245, 246}, s.HexSlice) +} + +func TestMappingArrayWithCustomUnmarshal(t *testing.T) { + var s struct { + HexArray [2]customUnmarshalParamHex `form:"hex_array"` + } + err := mappingByPtr(&s, formSource{"hex_array": {`f5`, `f6`}}, "form") + assert.NoError(t, err) + + assert.EqualValues(t, [2]customUnmarshalParamHex{245, 246}, s.HexArray) +}