Skip to content

Commit 25fa392

Browse files
committed
fix #245, always reuse existing value even UseNumber
1 parent d51e841 commit 25fa392

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"sync"
88
"unsafe"
99
"github.com/modern-go/concurrent"
10+
"reflect"
1011
)
1112

1213
// Config customize how the API should behave.
@@ -192,6 +193,11 @@ func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) {
192193

193194
func (cfg *frozenConfig) useNumber(extension DecoderExtension) {
194195
extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
196+
exitingValue := *((*interface{})(ptr))
197+
if exitingValue != nil && reflect.TypeOf(exitingValue).Kind() == reflect.Ptr {
198+
iter.ReadVal(exitingValue)
199+
return
200+
}
195201
if iter.WhatIsNext() == NumberValue {
196202
*((*interface{})(ptr)) = json.Number(iter.readNumberAsString())
197203
} else {

misc_tests/jsoniter_object_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,20 @@ func Test_reader_and_load_more(t *testing.T) {
130130
obj := TestObject{}
131131
should.Nil(decoder.Decode(&obj))
132132
}
133+
134+
func Test_unmarshal_into_existing_value(t *testing.T) {
135+
should := require.New(t)
136+
type TestObject struct {
137+
Field1 int
138+
Field2 interface{}
139+
}
140+
var obj TestObject
141+
m := map[string]interface{}{}
142+
obj.Field2 = &m
143+
cfg := jsoniter.Config{UseNumber: true}.Froze()
144+
err := cfg.Unmarshal([]byte(`{"Field1":1,"Field2":{"k":"v"}}`), &obj)
145+
should.NoError(err)
146+
should.Equal(map[string]interface{}{
147+
"k": "v",
148+
}, m)
149+
}

0 commit comments

Comments
 (0)