diff --git a/huma.go b/huma.go index 9ef44a72..0f30ecb4 100644 --- a/huma.go +++ b/huma.go @@ -1293,12 +1293,22 @@ func Register[I, O any](api API, op Operation, handler func(context.Context, *I) }) } } else { - // Set defaults for any fields that were not in the input. + // Set defaults for any fields that were not in the input: + atLeastOneFieldIsOverridden := false defaults.Every(v, func(item reflect.Value, def any) { - if item.IsZero() { + if item.IsZero() && !reflect.ValueOf(def).IsZero() { + // There is one caveat here: + // - IF the default value is not the 'zero' of the field type + // - AND the 'zero' of the field type is a valid value specified in the input + // - THEN the input required field value is overridden with a different value item.Set(reflect.Indirect(reflect.ValueOf(def))) + atLeastOneFieldIsOverridden = true } }) + // Restore wrongly overridden input values if any + if atLeastOneFieldIsOverridden { + _ = api.Unmarshal(ctx.Header("Content-Type"), body, f.Addr().Interface()) + } } } diff --git a/huma_test.go b/huma_test.go index 15240e57..e80ba803 100644 --- a/huma_test.go +++ b/huma_test.go @@ -627,14 +627,17 @@ func TestFeatures(t *testing.T) { assert.Equal(t, 5, input.Body.Count) assert.Equal(t, []string{"foo", "bar"}, input.Body.Tags) assert.Equal(t, []int{1, 2, 3}, input.Body.Numbers) + assert.Len(t, input.Body.Items, 2) assert.Equal(t, 1, input.Body.Items[0].ID) assert.True(t, input.Body.Items[0].Verified) + assert.Equal(t, 1, input.Body.Items[1].ID) + assert.False(t, input.Body.Items[1].Verified) return nil, nil }) }, Method: http.MethodPut, URL: "/body", - Body: `{"items": [{"id": 1}]}`, + Body: `{"items": [{"id": 1}, {"id": 1, "verified": false}]}`, }, { Name: "request-body-required",