diff --git a/decode.go b/decode.go index cf3fde2..7046c5a 100644 --- a/decode.go +++ b/decode.go @@ -656,9 +656,12 @@ func objectIntoStruct(structPtr reflect.Value) func(*ObjectDecoder) error { structValue := structPtr.Elem() f := fieldByName(structValue, k) if f == zeroValue { - return errors.Errorf("unable to decode entry: no field found named/tagged %q", k) - } - if err := o.Decode(f.Addr().Interface()); err != nil { + // Discard value with no matching field. + // TODO could be more efficient with custom discardValue() method + if _, err := o.decodeInterface(); err != nil { + return errors.Wrapf(err, "failed to discard value for %q with call #%d", k, o.count) + } + } else if err := o.Decode(f.Addr().Interface()); err != nil { return errors.Wrapf(err, "failed to decode value for %q with call #%d", k, o.count) } } diff --git a/decode_test.go b/decode_test.go index b289f73..222e8d2 100644 --- a/decode_test.go +++ b/decode_test.go @@ -44,3 +44,26 @@ func (tc *testCase) unmarshalBlock(t *testing.T) { expected, expected, actual.Elem().Interface(), actual.Elem().Interface()) } } + +func TestUnmarshalDiscardUnknownFields(t *testing.T) { + type val struct{ A int8 } + + exp := val{8} + var got val + + bin := []byte{'{', 'U', 0x01, 'A', 'i', 0x08, 'U', 0x01, 'b', 'i', 0x05, '}'} + + if err := Unmarshal(bin, &got); err != nil { + t.Fatal(err) + } else if got != exp { + t.Errorf("\nexpected: %T %v \nbut got: %T %v", exp, exp, got, got) + } + + block := "[{]\n\t[U][1][A][i][8]\n\t[U][1][B][i][5]\n[}]" + + if err := UnmarshalBlock([]byte(block), &got); err != nil { + t.Fatal(err) + } else if got != exp { + t.Errorf("\nexpected: %T %v \nbut got: %T %v", exp, exp, got, got) + } +}