diff --git a/huma.go b/huma.go index 3c0e663d..bd7d5458 100644 --- a/huma.go +++ b/huma.go @@ -402,7 +402,6 @@ func _findInType[T comparable](t reflect.Type, path []int, result *findResult[T] if _, ok := visited[t]; ok { return } - visited[t] = struct{}{} for i := 0; i < t.NumField(); i++ { f := t.Field(i) if !f.IsExported() { @@ -425,7 +424,9 @@ func _findInType[T comparable](t reflect.Type, path []int, result *findResult[T] // Always process embedded structs and named fields which are not // structs. If `recurseFields` is true then we also process named // struct fields recursively. + visited[t] = struct{}{} _findInType(f.Type, fi, result, onType, onField, recurseFields, visited, ignore...) + delete(visited, t) } } case reflect.Slice: diff --git a/huma_test.go b/huma_test.go index 2fe83521..01ced429 100644 --- a/huma_test.go +++ b/huma_test.go @@ -72,6 +72,10 @@ type BodyContainer struct { type CustomStringParam string +type StructWithDefaultField struct { + Field string `json:"field" default:"default"` +} + func TestFeatures(t *testing.T) { for _, feature := range []struct { Name string @@ -628,6 +632,11 @@ func TestFeatures(t *testing.T) { ID int `json:"id"` Verified bool `json:"verified,omitempty" default:"true"` } `json:"items,omitempty"` + // Test defaults for fields in the same linked struct. Even though + // we have seen the struct before we still need to set the default + // since it's a new/different field. + S1 StructWithDefaultField `json:"s1,omitempty"` + S2 StructWithDefaultField `json:"s2,omitempty"` } }) (*struct{}, error) { assert.Equal(t, "Huma", input.Body.Name) @@ -636,6 +645,8 @@ func TestFeatures(t *testing.T) { assert.Equal(t, []int{1, 2, 3}, input.Body.Numbers) assert.Equal(t, 1, input.Body.Items[0].ID) assert.True(t, input.Body.Items[0].Verified) + assert.Equal(t, "default", input.Body.S1.Field) + assert.Equal(t, "default", input.Body.S2.Field) return nil, nil }) },