1
0
mirror of https://github.com/json-iterator/go.git synced 2025-02-07 19:30:06 +02:00

#60 support read interface{} as json.Number

This commit is contained in:
Tao Wen 2017-06-18 15:22:37 +08:00
parent 77dcffe77d
commit 7a049ec79c
3 changed files with 31 additions and 10 deletions

View File

@ -13,9 +13,7 @@ package jsoniter
import (
"bytes"
"encoding/json"
"io"
"unsafe"
)
// Unmarshal adapts to json/encoding Unmarshal API
@ -95,13 +93,9 @@ func (adapter *AdaptedDecoder) Buffered() io.Reader {
}
func (decoder *AdaptedDecoder) UseNumber() {
RegisterTypeDecoder("interface {}", func(ptr unsafe.Pointer, iter *Iterator) {
if iter.WhatIsNext() == Number {
*((*interface{})(ptr)) = json.Number(iter.readNumberAsString())
} else {
*((*interface{})(ptr)) = iter.Read()
}
})
origCfg := decoder.iter.cfg.configBeforeFrozen
origCfg.UseNumber = true
decoder.iter.cfg = origCfg.Froze()
}
func NewEncoder(writer io.Writer) *AdaptedEncoder {

View File

@ -6,6 +6,7 @@ import (
"reflect"
"sync/atomic"
"unsafe"
"encoding/json"
)
type Config struct {
@ -14,6 +15,7 @@ type Config struct {
SupportUnexportedStructFields bool
EscapeHtml bool
SortMapKeys bool
UseNumber bool
}
type frozenConfig struct {
@ -27,7 +29,9 @@ type frozenConfig struct {
iteratorPool chan *Iterator
}
var ConfigDefault = Config{}.Froze()
var ConfigDefault = Config{
EscapeHtml: true,
}.Froze()
// Trying to be 100% compatible with standard library behavior
var ConfigCompatibleWithStandardLibrary = Config{
@ -57,10 +61,23 @@ func (cfg Config) Froze() *frozenConfig {
if cfg.EscapeHtml {
frozenConfig.escapeHtml()
}
if cfg.UseNumber {
frozenConfig.useNumber()
}
frozenConfig.configBeforeFrozen = cfg
return frozenConfig
}
func (cfg *frozenConfig) useNumber() {
cfg.addDecoderToCache(reflect.TypeOf((*interface{})(nil)).Elem(), &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
if iter.WhatIsNext() == Number {
*((*interface{})(ptr)) = json.Number(iter.readNumberAsString())
} else {
*((*interface{})(ptr)) = iter.Read()
}
}})
}
// RegisterExtension can register a custom extension
func (cfg *frozenConfig) registerExtension(extension ExtensionFunc) {
cfg.extensions = append(cfg.extensions, extension)

View File

@ -152,3 +152,13 @@ func Test_nil_non_empty_interface(t *testing.T) {
should.NotNil(json.Unmarshal(b, &obj))
should.NotNil(Unmarshal(b, &obj))
}
func Test_read_large_number_as_interface(t *testing.T) {
should := require.New(t)
var val interface{}
err := Config{UseNumber: true}.Froze().UnmarshalFromString(`123456789123456789123456789`, &val)
should.Nil(err)
output, err := MarshalToString(val)
should.Nil(err)
should.Equal(`123456789123456789123456789`, output)
}