From 4bce081dac22f133028166937c2ea3bccafa3a03 Mon Sep 17 00:00:00 2001 From: fbrandao Date: Mon, 21 Aug 2023 15:19:19 +0000 Subject: [PATCH 1/2] Fix for issue 464 --- decode_test.go | 25 +++++++++++++++++++++++++ helper_test.go | 14 +++++++++++++- internal/decoder/struct.go | 26 ++++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/decode_test.go b/decode_test.go index df914ed..6e87f17 100644 --- a/decode_test.go +++ b/decode_test.go @@ -4050,3 +4050,28 @@ func TestIssue429(t *testing.T) { } } } + +func TestIssue464(t *testing.T) { + type testStruct struct { + Name string + Value int + Description string + } + + jsonValue := []byte("{\"Name\":\"Test Name\",\"Value\":\"incorrect\",\"Description\":\"Test Description\"}") + + jsonData := testStruct{} + err := stdjson.Unmarshal(jsonValue, &jsonData) + assertIsType(t, "Incorrect error type stdjson", &stdjson.UnmarshalTypeError{}, err) + + gojsonData := testStruct{} + err = json.Unmarshal(jsonValue, &gojsonData) + assertIsType(t, "Incorrect error type go-json", &json.UnmarshalTypeError{}, err) + + assertEq(t, "Incorrect name stdjson", "Test Name", jsonData.Name) + assertEq(t, "Incorrect name go-json", "Test Name", gojsonData.Name) + assertEq(t, "Incorrect value stdjson", 0, jsonData.Value) + assertEq(t, "Incorrect value go-json", 0, gojsonData.Value) + assertEq(t, "Incorrect description stdjson", "Test Description", jsonData.Description) + assertEq(t, "Incorrect description go-json", "Test Description", gojsonData.Description) +} diff --git a/helper_test.go b/helper_test.go index 53157ce..7f52256 100644 --- a/helper_test.go +++ b/helper_test.go @@ -1,6 +1,9 @@ package json_test -import "testing" +import ( + "reflect" + "testing" +) func assertErr(t *testing.T, err error) { t.Helper() @@ -22,3 +25,12 @@ func assertNeq(t *testing.T, msg string, exp interface{}, act interface{}) { t.Fatalf("failed to test for %s. expected value is not [%v] but got same value", msg, act) } } + +func assertIsType(t *testing.T, msg string, exp interface{}, act interface{}) { + t.Helper() + expType := reflect.TypeOf(exp) + actType := reflect.TypeOf(act) + if expType != actType { + t.Fatalf("failed to test for %s. exp[%v] bug act=[%v]", msg, expType, actType) + } +} diff --git a/internal/decoder/struct.go b/internal/decoder/struct.go index 313da15..a1436fc 100644 --- a/internal/decoder/struct.go +++ b/internal/decoder/struct.go @@ -778,6 +778,7 @@ func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsaf if firstWin { seenFields = make(map[int]struct{}, d.fieldUniqueNameNum) } + var lastTypeMismatchError error for { c, field, err := d.keyDecoder(d, buf, cursor) if err != nil { @@ -805,7 +806,16 @@ func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsaf } else { c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset)) if err != nil { - return 0, err + if _, ok := err.(*errors.UnmarshalTypeError); ok { + lastTypeMismatchError = err + c, err = skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + cursor = c + } else { + return 0, err + } } cursor = c seenFieldNum++ @@ -817,7 +827,16 @@ func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsaf } else { c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset)) if err != nil { - return 0, err + if _, ok := err.(*errors.UnmarshalTypeError); ok { + lastTypeMismatchError = err + c, err = skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + cursor = c + } else { + return 0, err + } } cursor = c } @@ -831,6 +850,9 @@ func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsaf cursor = skipWhiteSpace(buf, cursor) if char(b, cursor) == '}' { cursor++ + if lastTypeMismatchError != nil { + return 0, lastTypeMismatchError + } return cursor, nil } if char(b, cursor) != ',' { From b29e1ad08b231efe2fa33fa80041e817dc68af1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Nascimento=20Brand=C3=A3o?= Date: Mon, 21 Aug 2023 12:33:52 -0300 Subject: [PATCH 2/2] Update struct.go --- internal/decoder/struct.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/decoder/struct.go b/internal/decoder/struct.go index a1436fc..33cea98 100644 --- a/internal/decoder/struct.go +++ b/internal/decoder/struct.go @@ -812,7 +812,6 @@ func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsaf if err != nil { return 0, err } - cursor = c } else { return 0, err } @@ -833,7 +832,6 @@ func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsaf if err != nil { return 0, err } - cursor = c } else { return 0, err }