diff --git a/decode_test.go b/decode_test.go index 8f32ced..ba4df51 100644 --- a/decode_test.go +++ b/decode_test.go @@ -4057,3 +4057,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..33cea98 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,15 @@ 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 + } + } else { + return 0, err + } } cursor = c seenFieldNum++ @@ -817,7 +826,15 @@ 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 + } + } else { + return 0, err + } } cursor = c } @@ -831,6 +848,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) != ',' {