diff --git a/primitives/DataProviders.go b/primitives/DataProviders.go index 19d8d28..16f01af 100644 --- a/primitives/DataProviders.go +++ b/primitives/DataProviders.go @@ -44,6 +44,11 @@ func NewMapDataProvider[T any](m map[string]T) DataProvider { // Tries to create a map data provider from any value if it cannot it will return an empty data provider (which will always return nil) func NewAnyDataProvider(val any) DataProvider { + dataProvider, _ := TryNewAnyDataProvider(val) + return dataProvider +} + +func TryNewAnyDataProvider(val any) (DataProvider, bool) { x := reflect.ValueOf(val) switch x.Kind() { @@ -51,33 +56,33 @@ func NewAnyDataProvider(val any) DataProvider { keyTyp := x.Type().Key() if keyTyp.Kind() != reflect.String { - return &EmptyDataProvider{} + return &EmptyDataProvider{}, false } valTyp := x.Type().Elem() switch valTyp.Kind() { // TODO: add more types case reflect.String: - return NewMapDataProvider(x.Interface().(map[string]string)) + return NewMapDataProvider(x.Interface().(map[string]string)), true case reflect.Int: - return NewMapDataProvider(x.Interface().(map[string]int)) + return NewMapDataProvider(x.Interface().(map[string]int)), true case reflect.Float64: - return NewMapDataProvider(x.Interface().(map[string]float64)) + return NewMapDataProvider(x.Interface().(map[string]float64)), true case reflect.Bool: - return NewMapDataProvider(x.Interface().(map[string]bool)) + return NewMapDataProvider(x.Interface().(map[string]bool)), true case reflect.Interface: - return NewMapDataProvider(x.Interface().(map[string]any)) + return NewMapDataProvider(x.Interface().(map[string]any)), true default: - return &EmptyDataProvider{} + return &EmptyDataProvider{}, false } case reflect.Pointer: if x.IsNil() { - return &EmptyDataProvider{} + return &EmptyDataProvider{}, false } - return NewAnyDataProvider(x.Elem().Interface()) + return TryNewAnyDataProvider(x.Elem().Interface()) default: - return &EmptyDataProvider{} + return &EmptyDataProvider{}, false } } diff --git a/slices.go b/slices.go index ac6c131..4f3e7ef 100644 --- a/slices.go +++ b/slices.go @@ -97,12 +97,7 @@ func (v *sliceProcessor) process(val any, dest any, errs p.ZogErrors, path p.Pat item := refVal.Index(idx).Interface() ptr := destVal.Index(idx).Addr().Interface() path := path.Push(fmt.Sprint(idx)) - if procesor, ok := v.schema.(*structProcessor); ok { - dp := p.NewAnyDataProvider(item) - procesor.process(dp, ptr, errs, path, ctx) - } else { - v.schema.process(item, ptr, errs, path, ctx) - } + v.schema.process(item, ptr, errs, path, ctx) } } diff --git a/slices_test.go b/slices_test.go index a77546e..09aeb36 100644 --- a/slices_test.go +++ b/slices_test.go @@ -136,6 +136,8 @@ func TestSliceOfStructs(t *testing.T) { var team Team errsMap := teamSchema.Parse(NewMapDataProvider(data), &team) - fmt.Printf("%+v", errsMap) - fmt.Printf("%+v", team) + assert.Nil(t, errsMap) + assert.Len(t, team.Users, 2) + assert.Equal(t, team.Users[0].Name, "Jane") + assert.Equal(t, team.Users[1].Name, "John") } diff --git a/struct.go b/struct.go index f1dc148..36d65b3 100644 --- a/struct.go +++ b/struct.go @@ -117,8 +117,10 @@ func (v *structProcessor) process(val any, dest any, errs p.ZogErrors, path p.Pa // 2. cast data as DataProvider dataProv, ok := val.(p.DataProvider) if !ok { - errs.Add(path, Errors.Wrap(fmt.Errorf("expected a DataProvider at path %s", path), "failed to validate field")) - return + if dataProv, ok = p.TryNewAnyDataProvider(val); !ok { + errs.Add(path, Errors.Wrap(fmt.Errorf("expected a DataProvider at path %s", path), "failed to validate field")) + return + } } // required