mirror of https://github.com/goccy/go-json.git
Fix decoding of slice element
This commit is contained in:
parent
46bdba4a65
commit
78e2bf2502
|
@ -7,14 +7,13 @@ import (
|
|||
)
|
||||
|
||||
type sliceDecoder struct {
|
||||
elemType *rtype
|
||||
isElemPointerType bool
|
||||
isElemUnmarshalJSONType bool
|
||||
valueDecoder decoder
|
||||
size uintptr
|
||||
arrayPool sync.Pool
|
||||
structName string
|
||||
fieldName string
|
||||
elemType *rtype
|
||||
isElemPointerType bool
|
||||
valueDecoder decoder
|
||||
size uintptr
|
||||
arrayPool sync.Pool
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
// If use reflect.SliceHeader, data type is uintptr.
|
||||
|
@ -32,11 +31,10 @@ const (
|
|||
|
||||
func newSliceDecoder(dec decoder, elemType *rtype, size uintptr, structName, fieldName string) *sliceDecoder {
|
||||
return &sliceDecoder{
|
||||
valueDecoder: dec,
|
||||
elemType: elemType,
|
||||
isElemPointerType: elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map,
|
||||
isElemUnmarshalJSONType: rtype_ptrTo(elemType).Implements(unmarshalJSONType),
|
||||
size: size,
|
||||
valueDecoder: dec,
|
||||
elemType: elemType,
|
||||
isElemPointerType: elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map,
|
||||
size: size,
|
||||
arrayPool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &sliceHeader{
|
||||
|
@ -123,11 +121,11 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
copySlice(d.elemType, dst, src)
|
||||
}
|
||||
ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size)
|
||||
if d.isElemUnmarshalJSONType {
|
||||
if d.isElemPointerType {
|
||||
**(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer
|
||||
} else {
|
||||
// assign new element to the slice
|
||||
typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
|
||||
} else if d.isElemPointerType {
|
||||
**(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer
|
||||
}
|
||||
if err := d.valueDecoder.decodeStream(s, depth, ep); err != nil {
|
||||
return err
|
||||
|
@ -236,11 +234,11 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
copySlice(d.elemType, dst, src)
|
||||
}
|
||||
ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size)
|
||||
if d.isElemUnmarshalJSONType {
|
||||
if d.isElemPointerType {
|
||||
**(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer
|
||||
} else {
|
||||
// assign new element to the slice
|
||||
typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
|
||||
} else if d.isElemPointerType {
|
||||
**(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer
|
||||
}
|
||||
c, err := d.valueDecoder.decode(buf, cursor, depth, ep)
|
||||
if err != nil {
|
||||
|
|
|
@ -3508,3 +3508,64 @@ func TestDecodeBackSlash(t *testing.T) {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestIssue218(t *testing.T) {
|
||||
type A struct {
|
||||
X int
|
||||
}
|
||||
type B struct {
|
||||
Y int
|
||||
}
|
||||
type S struct {
|
||||
A *A `json:"a,omitempty"`
|
||||
B *B `json:"b,omitempty"`
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
given []S
|
||||
expected []S
|
||||
}{
|
||||
{
|
||||
name: "A should be correct",
|
||||
given: []S{{
|
||||
A: &A{
|
||||
X: 1,
|
||||
},
|
||||
}},
|
||||
expected: []S{{
|
||||
A: &A{
|
||||
X: 1,
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
name: "B should be correct",
|
||||
given: []S{{
|
||||
B: &B{
|
||||
Y: 2,
|
||||
},
|
||||
}},
|
||||
expected: []S{{
|
||||
B: &B{
|
||||
Y: 2,
|
||||
},
|
||||
}},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := json.NewEncoder(&buf).Encode(test.given); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var actual []S
|
||||
if err := json.NewDecoder(bytes.NewReader(buf.Bytes())).Decode(&actual); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(test.expected, actual) {
|
||||
t.Fatalf("mismatch value: expected %v but got %v", test.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue