From b4d09053db1ba73dc0a5184caf162befd2e91373 Mon Sep 17 00:00:00 2001 From: Pratham Gadkari Date: Fri, 14 Nov 2025 23:44:50 +0530 Subject: [PATCH 1/2] fix(binding): support custom unmarshaler for slices & arrays --- binding/form_mapping.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/binding/form_mapping.go b/binding/form_mapping.go index 1244b522..6a07330a 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -186,7 +186,10 @@ type BindUnmarshaler interface { func trySetCustom(val string, value reflect.Value) (isSet bool, err error) { switch v := value.Addr().Interface().(type) { case BindUnmarshaler: - return true, v.UnmarshalParam(val) + if err := v.UnmarshalParam(val); err != nil { + return true, fmt.Errorf("invalid value %q: %w", val, err) + } + return true, nil } return false, nil } @@ -245,7 +248,10 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][ } if ok, err = trySetCustom(vs[0], value); ok { - return ok, err + if err != nil { + return true, fmt.Errorf("field %q: %w", field.Name, err) + } + return true, nil } if vs, err = trySplit(vs, field); err != nil { @@ -268,7 +274,10 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][ } if ok, err = trySetCustom(vs[0], value); ok { - return ok, err + if err != nil { + return true, fmt.Errorf("field %q: %w", field.Name, err) + } + return true, nil } if vs, err = trySplit(vs, field); err != nil { @@ -293,7 +302,10 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][ } } if ok, err := trySetCustom(val, value); ok { - return ok, err + if err != nil { + return true, fmt.Errorf("field %q: %w", field.Name, err) + } + return true, nil } return true, setWithProperType(val, value, field) } From 513a86e17fa3ffed325c7f4f41fa3a919ce32afd Mon Sep 17 00:00:00 2001 From: Pratham Gadkari Date: Sat, 15 Nov 2025 22:28:32 +0530 Subject: [PATCH 2/2] added tests for feature and coverage --- binding/form_mapping_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/binding/form_mapping_test.go b/binding/form_mapping_test.go index 006eddf1..d0086d31 100644 --- a/binding/form_mapping_test.go +++ b/binding/form_mapping_test.go @@ -715,3 +715,22 @@ func TestMappingEmptyValues(t *testing.T) { assert.Equal(t, []int{1, 2, 3}, s.SliceCsv) }) } + +type testCustom struct { + Value string +} + +func (t *testCustom) UnmarshalParam(param string) error { + t.Value = "prefix_" + param + return nil +} + +func TestTrySetCustomIntegration(t *testing.T) { + var s struct { + F testCustom `form:"f"` + } + + err := mappingByPtr(&s, formSource{"f": {"hello"}}, "form") + require.NoError(t, err) + assert.Equal(t, "prefix_hello", s.F.Value) +}