Browse Source

suport encode map[interface{}]interface{}

Tao Wen 7 năm trước cách đây
mục cha
commit
ca39e5af3e

+ 2 - 3
config.go

@@ -2,12 +2,12 @@ package jsoniter
 
 import (
 	"encoding/json"
+	"github.com/modern-go/concurrent"
 	"github.com/modern-go/reflect2"
 	"io"
+	"reflect"
 	"sync"
 	"unsafe"
-	"github.com/modern-go/concurrent"
-	"reflect"
 )
 
 // Config customize how the API should behave.
@@ -63,7 +63,6 @@ var ConfigFastest = Config{
 	ObjectFieldMustBeSimpleString: true, // do not unescape object field
 }.Froze()
 
-
 type frozenConfig struct {
 	configBeforeFrozen            Config
 	sortMapKeys                   bool

+ 1 - 1
extension_tests/extension_test.go

@@ -2,8 +2,8 @@ package test
 
 import (
 	"github.com/json-iterator/go"
-	"github.com/stretchr/testify/require"
 	"github.com/modern-go/reflect2"
+	"github.com/stretchr/testify/require"
 	"reflect"
 	"strconv"
 	"testing"

+ 6 - 6
extra/binary_as_string_codec.go

@@ -2,9 +2,9 @@ package extra
 
 import (
 	"github.com/json-iterator/go"
-	"unsafe"
-	"unicode/utf8"
 	"github.com/modern-go/reflect2"
+	"unicode/utf8"
+	"unsafe"
 )
 
 // safeSet holds the value true if the ASCII character with the given array
@@ -171,18 +171,18 @@ func (codec *binaryAsStringCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.St
 func readHex(iter *jsoniter.Iterator, b1, b2 byte) byte {
 	var ret byte
 	if b1 >= '0' && b1 <= '9' {
-		ret = b1-'0'
+		ret = b1 - '0'
 	} else if b1 >= 'a' && b1 <= 'f' {
-		ret = b1-'a'+10
+		ret = b1 - 'a' + 10
 	} else {
 		iter.ReportError("read hex", "expects 0~9 or a~f, but found "+string([]byte{b1}))
 		return 0
 	}
 	ret = ret * 16
 	if b2 >= '0' && b2 <= '9' {
-		ret = b2-'0'
+		ret = b2 - '0'
 	} else if b2 >= 'a' && b2 <= 'f' {
-		ret = b2-'a'+10
+		ret = b2 - 'a' + 10
 	} else {
 		iter.ReportError("read hex", "expects 0~9 or a~f, but found "+string([]byte{b2}))
 		return 0

+ 2 - 2
extra/binary_as_string_codec_test.go

@@ -1,9 +1,9 @@
 package extra
 
 import (
-	"testing"
-	"github.com/stretchr/testify/require"
 	"github.com/json-iterator/go"
+	"github.com/stretchr/testify/require"
+	"testing"
 )
 
 func init() {

+ 11 - 0
misc_tests/jsoniter_map_test.go

@@ -31,3 +31,14 @@ func Test_read_map_with_reader(t *testing.T) {
 	should.Equal(m2, m1)
 	should.Equal("1.0.76", m1["note"].(map[string]interface{})["CoreServices"].(map[string]interface{})["version_name"])
 }
+
+func Test_map_eface_of_eface(t *testing.T) {
+	should := require.New(t)
+	json := jsoniter.ConfigCompatibleWithStandardLibrary
+	output, err := json.MarshalToString(map[interface{}]interface{}{
+		"1": 2,
+		3:   "4",
+	})
+	should.NoError(err)
+	should.Equal(`{"1":2,"3":"4"}`, output)
+}

+ 22 - 0
reflect_map.go

@@ -3,6 +3,7 @@ package jsoniter
 import (
 	"fmt"
 	"github.com/modern-go/reflect2"
+	"io"
 	"reflect"
 	"sort"
 	"unsafe"
@@ -107,6 +108,9 @@ func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
 				stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
 			}
 		}
+		if typ.Kind() == reflect.Interface {
+			return &dynamicMapKeyEncoder{ctx, typ}
+		}
 		return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
 	}
 }
@@ -203,6 +207,21 @@ func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
 	return false
 }
 
+type dynamicMapKeyEncoder struct {
+	ctx     *ctx
+	valType reflect2.Type
+}
+
+func (encoder *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
+	obj := encoder.valType.UnsafeIndirect(ptr)
+	encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream)
+}
+
+func (encoder *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
+	obj := encoder.valType.UnsafeIndirect(ptr)
+	return encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj))
+}
+
 type mapEncoder struct {
 	mapType     *reflect2.UnsafeMapType
 	keyEncoder  ValEncoder
@@ -253,6 +272,9 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
 		subStream.buf = make([]byte, 0, 64)
 		key, elem := mapIter.UnsafeNext()
 		encoder.keyEncoder.Encode(key, subStream)
+		if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil {
+			stream.Error = subStream.Error
+		}
 		encodedKey := subStream.Buffer()
 		subIter.ResetBytes(encodedKey)
 		decodedKey := subIter.ReadString()

+ 1 - 2
value_tests/slice_test.go

@@ -6,7 +6,7 @@ func init() {
 		[]interface{}{"hello"},
 		nilSlice,
 		&nilSlice,
-		selectedMarshalCase{[]byte{1,2,3}},
+		[]byte{1, 2, 3},
 	)
 	unmarshalCases = append(unmarshalCases, unmarshalCase{
 		ptr:   (*[]string)(nil),
@@ -20,6 +20,5 @@ func init() {
 	}, unmarshalCase{
 		ptr:   (*[]byte)(nil),
 		input: `"aGVsbG8="`,
-		selected: true,
 	})
 }

+ 1 - 1
value_tests/value_test.go

@@ -4,8 +4,8 @@ import (
 	"encoding/json"
 	"fmt"
 	"github.com/json-iterator/go"
-	"github.com/stretchr/testify/require"
 	"github.com/modern-go/reflect2"
+	"github.com/stretchr/testify/require"
 	"testing"
 )