Repository: getkin/kin-openapi (go)

Issue:
bug: validation of a slice of non-empty interface against an array schema should pass
### Context

An array schema validates only against a slice of empty interface: `[]interface{}{...}`. If a slice of non-empty interface (e.g. `[]string{...}`) is attempted to validate against that schema, this error occurs: `unhandled value of type []string`

### Reproduce

```go
package main

import (
	"fmt"

	"github.com/getkin/kin-openapi/openapi3"
)

func main() {
	schema := &openapi3.Schema{
		Type:        "array",
		UniqueItems: true,
		Items:       openapi3.NewStringSchema().NewRef(),
	}
	data := []string{"foo", "bar"}
	err := schema.VisitJSON(data)
	fmt.Println(err)
}
```

### Expected

In this case, a nil error should be printed because `VisitJSON` would recognize that `data` is a slice.

There is a bug in `VisitJSON` where the `[]interface{}` case does not cover all slices: https://github.com/getkin/kin-openapi/blob/9f99fee5a643dd7522772022cda4eee8b7f3f614/openapi3/schema.go#L1108-L1109

Pull request description:
openapi3: fix validation of non-empty interface slice value against array schema
Resolves #751 

In `VisitJSON` after the `switch` block, it checks `value`'s Kind. If it is a Slice, it transforms the `value` into a slice of empty interfaces and passes it to `visitJSONArray`

`TestSchemas` did not catch this because the data (`AllValid` and `AllInvalid`) are coerced to empty interface types.

Patch:
diff --git a/openapi3/schema.go b/openapi3/schema.go
index 0d1d183..415c281 100644
--- a/openapi3/schema.go
+++ b/openapi3/schema.go
@@ -1120,6 +1120,17 @@ func (schema *Schema) visitJSON(settings *schemaValidationSettings, value interf
 			return schema.visitJSONObject(settings, values)
 		}
 	}
+
+	// Catch slice of non-empty interface type
+	if reflect.TypeOf(value).Kind() == reflect.Slice {
+		valueR := reflect.ValueOf(value)
+		newValue := make([]interface{}, valueR.Len())
+		for i := 0; i < valueR.Len(); i++ {
+			newValue[i] = valueR.Index(i).Interface()
+		}
+		return schema.visitJSONArray(settings, newValue)
+	}
+
 	return &SchemaError{
 		Value:                 value,
 		Schema:                schema,


Test patch:
diff --git a/openapi3/schema_test.go b/openapi3/schema_test.go
index 2bd9848..2666979 100644
--- a/openapi3/schema_test.go
+++ b/openapi3/schema_test.go
@@ -1354,3 +1354,15 @@ enum:
 	err = schema.VisitJSON(map[string]interface{}{"d": "e"})
 	require.Error(t, err)
 }
+
+func TestIssue751(t *testing.T) {
+	schema := &Schema{
+		Type:        "array",
+		UniqueItems: true,
+		Items:       NewStringSchema().NewRef(),
+	}
+	validData := []string{"foo", "bar"}
+	invalidData := []string{"foo", "foo"}
+	require.NoError(t, schema.VisitJSON(validData))
+	require.ErrorContains(t, schema.VisitJSON(invalidData), "duplicate items found")
+}