1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-23 11:37:32 +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 ( import (
"bytes" "bytes"
"encoding/json"
"io" "io"
"unsafe"
) )
// Unmarshal adapts to json/encoding Unmarshal API // Unmarshal adapts to json/encoding Unmarshal API
@ -95,13 +93,9 @@ func (adapter *AdaptedDecoder) Buffered() io.Reader {
} }
func (decoder *AdaptedDecoder) UseNumber() { func (decoder *AdaptedDecoder) UseNumber() {
RegisterTypeDecoder("interface {}", func(ptr unsafe.Pointer, iter *Iterator) { origCfg := decoder.iter.cfg.configBeforeFrozen
if iter.WhatIsNext() == Number { origCfg.UseNumber = true
*((*interface{})(ptr)) = json.Number(iter.readNumberAsString()) decoder.iter.cfg = origCfg.Froze()
} else {
*((*interface{})(ptr)) = iter.Read()
}
})
} }
func NewEncoder(writer io.Writer) *AdaptedEncoder { func NewEncoder(writer io.Writer) *AdaptedEncoder {

View File

@ -6,6 +6,7 @@ import (
"reflect" "reflect"
"sync/atomic" "sync/atomic"
"unsafe" "unsafe"
"encoding/json"
) )
type Config struct { type Config struct {
@ -14,6 +15,7 @@ type Config struct {
SupportUnexportedStructFields bool SupportUnexportedStructFields bool
EscapeHtml bool EscapeHtml bool
SortMapKeys bool SortMapKeys bool
UseNumber bool
} }
type frozenConfig struct { type frozenConfig struct {
@ -27,7 +29,9 @@ type frozenConfig struct {
iteratorPool chan *Iterator iteratorPool chan *Iterator
} }
var ConfigDefault = Config{}.Froze() var ConfigDefault = Config{
EscapeHtml: true,
}.Froze()
// Trying to be 100% compatible with standard library behavior // Trying to be 100% compatible with standard library behavior
var ConfigCompatibleWithStandardLibrary = Config{ var ConfigCompatibleWithStandardLibrary = Config{
@ -57,10 +61,23 @@ func (cfg Config) Froze() *frozenConfig {
if cfg.EscapeHtml { if cfg.EscapeHtml {
frozenConfig.escapeHtml() frozenConfig.escapeHtml()
} }
if cfg.UseNumber {
frozenConfig.useNumber()
}
frozenConfig.configBeforeFrozen = cfg frozenConfig.configBeforeFrozen = cfg
return frozenConfig 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 // RegisterExtension can register a custom extension
func (cfg *frozenConfig) registerExtension(extension ExtensionFunc) { func (cfg *frozenConfig) registerExtension(extension ExtensionFunc) {
cfg.extensions = append(cfg.extensions, extension) 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(json.Unmarshal(b, &obj))
should.NotNil(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)
}