Skip to content

Commit bfe9ff9

Browse files
vikstrousclaudevikstrous2
authored
fix: respect Binder interface for primitive types in BindStringToObject (#86)
Previously, the Binder interface was only checked within the struct case of the type switch, causing primitive types (strings, ints, etc.) that implement Binder to bypass their custom binding logic. This fix moves the Binder check to the beginning of BindStringToObject, ensuring all types implementing Binder use their custom Bind method, regardless of their underlying type. The redundant check in the struct case has been removed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Viktor Stanchev <viktor@anchorlabs.com>
1 parent b76a24f commit bfe9ff9

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

bindstring.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ type BindStringToObjectOptions struct {
4949
func BindStringToObjectWithOptions(src string, dst interface{}, opts BindStringToObjectOptions) error {
5050
var err error
5151

52+
// Check if the destination implements Binder interface before any reflection
53+
if binder, ok := dst.(Binder); ok {
54+
return binder.Bind(src)
55+
}
56+
5257
v := reflect.ValueOf(dst)
5358
t := reflect.TypeOf(dst)
5459

@@ -134,11 +139,6 @@ func BindStringToObjectWithOptions(src string, dst interface{}, opts BindStringT
134139
}
135140
fallthrough
136141
case reflect.Struct:
137-
// if this is not of type Time or of type Date look to see if this is of type Binder.
138-
if dstType, ok := dst.(Binder); ok {
139-
return dstType.Bind(src)
140-
}
141-
142142
if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
143143
// Don't fail on empty string.
144144
if src == "" {

bindstring_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ import (
2626
"github.com/oapi-codegen/runtime/types"
2727
)
2828

29+
// CustomStringBinder is a string type that implements Binder but not TextUnmarshaler
30+
// This tests that Binder interface is checked for primitive types
31+
type CustomStringBinder string
32+
33+
func (c *CustomStringBinder) Bind(src string) error {
34+
// Custom binding logic: add a prefix to demonstrate the Bind method was called
35+
*c = CustomStringBinder("CUSTOM:" + src)
36+
return nil
37+
}
38+
2939
func TestBindStringToObject(t *testing.T) {
3040
var i int
3141
assert.NoError(t, BindStringToObject("5", &i))
@@ -211,6 +221,12 @@ func TestBindStringToObject(t *testing.T) {
211221
assert.NoError(t, BindStringToObject(uuidString, &dstUUID))
212222
assert.Equal(t, dstUUID.String(), uuidString)
213223

224+
// Checks that primitive types implementing Binder are respected
225+
// This tests the fix for ensuring Binder is checked before type reflection
226+
var customString CustomStringBinder
227+
assert.NoError(t, BindStringToObject("hello", &customString))
228+
assert.Equal(t, CustomStringBinder("CUSTOM:hello"), customString)
229+
214230
}
215231

216232
// TestBindStringToObject_ByteSlice tests that BindStringToObject correctly handles

0 commit comments

Comments
 (0)