Przeglądaj źródła

#60 support read interface{} as json.Number

Tao Wen 8 lat temu
rodzic
commit
7a049ec79c
3 zmienionych plików z 31 dodań i 10 usunięć
  1. 3 9
      feature_adapter.go
  2. 18 1
      feature_config.go
  3. 10 0
      jsoniter_interface_test.go

+ 3 - 9
feature_adapter.go

@@ -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 {

+ 18 - 1
feature_config.go

@@ -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)

+ 10 - 0
jsoniter_interface_test.go

@@ -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)
+}