Merge pull request #321 from goccy/feature/add-invalid-decoder

Add invalid decoder to delay type error judgment at decode
This commit is contained in:
Masaaki Goshima 2022-01-13 21:54:24 +09:00 committed by GitHub
commit 0f7e1f926f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 17 deletions

View File

@ -3776,3 +3776,16 @@ func TestIssue282(t *testing.T) {
t.Fatalf("failed to assign map value") t.Fatalf("failed to assign map value")
} }
} }
func TestDecodeStructFieldMap(t *testing.T) {
type Foo struct {
Bar map[float64]float64 `json:"bar,omitempty"`
}
var v Foo
if err := json.Unmarshal([]byte(`{"name":"test"}`), &v); err != nil {
t.Fatal(err)
}
if v.Bar != nil {
t.Fatalf("failed to decode v.Bar = %+v", v.Bar)
}
}

View File

@ -9,7 +9,6 @@ import (
"unicode" "unicode"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "github.com/goccy/go-json/internal/runtime"
) )
@ -126,13 +125,7 @@ func compile(typ *runtime.Type, structName, fieldName string, structTypeToDecode
case reflect.Func: case reflect.Func:
return compileFunc(typ, structName, fieldName) return compileFunc(typ, structName, fieldName)
} }
return nil, &errors.UnmarshalTypeError{ return newInvalidDecoder(typ, structName, fieldName), nil
Value: "object",
Type: runtime.RType2Type(typ),
Offset: 0,
Struct: structName,
Field: fieldName,
}
} }
func isStringTagSupportedType(typ *runtime.Type) bool { func isStringTagSupportedType(typ *runtime.Type) bool {
@ -174,17 +167,9 @@ func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeTo
case *ptrDecoder: case *ptrDecoder:
dec = t.dec dec = t.dec
default: default:
goto ERROR return newInvalidDecoder(typ, structName, fieldName), nil
} }
} }
ERROR:
return nil, &errors.UnmarshalTypeError{
Value: "object",
Type: runtime.RType2Type(typ),
Offset: 0,
Struct: structName,
Field: fieldName,
}
} }
func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {

View File

@ -0,0 +1,45 @@
package decoder
import (
"reflect"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type invalidDecoder struct {
typ *runtime.Type
kind reflect.Kind
structName string
fieldName string
}
func newInvalidDecoder(typ *runtime.Type, structName, fieldName string) *invalidDecoder {
return &invalidDecoder{
typ: typ,
kind: typ.Kind(),
structName: structName,
fieldName: fieldName,
}
}
func (d *invalidDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
return &errors.UnmarshalTypeError{
Value: "object",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
Struct: d.structName,
Field: d.fieldName,
}
}
func (d *invalidDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
return 0, &errors.UnmarshalTypeError{
Value: "object",
Type: runtime.RType2Type(d.typ),
Offset: cursor,
Struct: d.structName,
Field: d.fieldName,
}
}