From ec1d297b6bb9993c93b98fa0309d33134aa578b7 Mon Sep 17 00:00:00 2001 From: Charlie Tonneslan Date: Mon, 18 May 2026 10:54:42 -0400 Subject: [PATCH] decode: skip "-" tagged fields so ErrorUnset doesn't flag them Closes #89. mapstructure:"-" means a field is opted out of decoding, but the decoder still walked it during struct iteration and added the literal "-" key to Metadata.Unset, which made ErrorUnset trip on it. Honour the tag by continuing past the field, matching how the encoder already handles it. Signed-off-by: Charlie Tonneslan --- mapstructure.go | 5 +++++ mapstructure_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/mapstructure.go b/mapstructure.go index 9087fd96..0c0be979 100644 --- a/mapstructure.go +++ b/mapstructure.go @@ -1663,6 +1663,11 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e continue } tagValue = strings.SplitN(tagValue, ",", 2)[0] + // `mapstructure:"-"` opts the field out of decoding entirely. Don't + // then turn around and report a "-" key as Unset/missing. + if tagValue == "-" { + continue + } if tagValue != "" { fieldName = tagValue } else { diff --git a/mapstructure_test.go b/mapstructure_test.go index baf40dfe..c0701966 100644 --- a/mapstructure_test.go +++ b/mapstructure_test.go @@ -1714,6 +1714,34 @@ func TestDecoder_ErrorUnset(t *testing.T) { } } +func TestDecoder_ErrorUnset_IgnoresDashTaggedField(t *testing.T) { + // Regression for #89: a field tagged `mapstructure:"-"` is opted out + // of decoding, so ErrorUnset shouldn't flag it as missing. + t.Parallel() + + input := map[string]any{ + "foo": "bar", + } + + var result struct { + Foo string `mapstructure:"foo"` + Bar string `mapstructure:"-"` + } + config := &DecoderConfig{ + ErrorUnset: true, + Result: &result, + } + + decoder, err := NewDecoder(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + if err := decoder.Decode(input); err != nil { + t.Fatalf("unexpected error: %v", err) + } +} + func TestDecoder_ErrorUnset_AllowUnsetPointer(t *testing.T) { t.Parallel()