diff --git a/dot.go b/dot.go index e0dc090..08900eb 100644 --- a/dot.go +++ b/dot.go @@ -119,6 +119,12 @@ func (d *Dot) insert(innerObj reflect.Value, previousPath string, parts []string if innerObj.Kind() == reflect.Chan { return d.inChannel(innerObj, currentPath, remainingParts) } + case reflect.Interface: + return fmt.Errorf( + "the type in %s is interface{} and it is impossible to further predict the path", + previousPath, + ) + default: // If it is logical to already insert a value in the specified path, // but the path has not yet ended, it means that the path is specified incorrectly @@ -140,7 +146,7 @@ func set(innerObj reflect.Value, currentPath string, content any, source Scenari value := reflect.ValueOf(content) // Checking for type matching - if innerObj.Type() != value.Type() { + if innerObj.Type() != value.Type() && innerObj.Kind() != reflect.Interface { return fmt.Errorf( errMsg[source], innerObj.Type(), value.Type(), currentPath, ) diff --git a/dot_test.go b/dot_test.go index 94b36e0..fcf554f 100644 --- a/dot_test.go +++ b/dot_test.go @@ -40,6 +40,7 @@ type Data struct { K map[uint64]string L map[Key]string M map[[2]int]string + N map[string]any } func TestInvalidType(t *testing.T) { @@ -76,6 +77,35 @@ func TestNewFailure(t *testing.T) { } } +func TestSetInterface(t *testing.T) { + data := Data{ + N: map[string]any{ + "First": Info{}, + }, + } + + obj, err := dot.New(&data) + assert.Nil(t, err) + + // On the path of data insertion the type interface{} is found, + // further it is impossible to define the path + if err := obj.Insert("N.First.Title", "New Title"); assert.Error(t, err) { + assert.ErrorContains( + t, err, "the type in N.First is interface{} and it is impossible to further predict the path", + ) + } + + // If the final destination in the path is interface{}, + // then we insert the provided value into it + if err := obj.Insert("N.First", Info{Title: "Any Title"}); assert.NoError(t, err) { + if value, exists := data.N["First"]; assert.True(t, exists) { + if n, ok := value.(Info); assert.True(t, ok) { + assert.Exactly(t, "Any Title", n.Title) + } + } + } +} + func TestUnknownPlaceholder(t *testing.T) { data := Data{} obj, err := dot.New(&data)