Skip to content

Commit ca39e5a

Browse files
committed
suport encode map[interface{}]interface{}
1 parent 39acec9 commit ca39e5a

File tree

8 files changed

+46
-15
lines changed

8 files changed

+46
-15
lines changed

config.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ package jsoniter
22

33
import (
44
"encoding/json"
5+
"github.com/modern-go/concurrent"
56
"github.com/modern-go/reflect2"
67
"io"
8+
"reflect"
79
"sync"
810
"unsafe"
9-
"github.com/modern-go/concurrent"
10-
"reflect"
1111
)
1212

1313
// Config customize how the API should behave.
@@ -63,7 +63,6 @@ var ConfigFastest = Config{
6363
ObjectFieldMustBeSimpleString: true, // do not unescape object field
6464
}.Froze()
6565

66-
6766
type frozenConfig struct {
6867
configBeforeFrozen Config
6968
sortMapKeys bool

extension_tests/extension_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package test
22

33
import (
44
"github.com/json-iterator/go"
5-
"github.com/stretchr/testify/require"
65
"github.com/modern-go/reflect2"
6+
"github.com/stretchr/testify/require"
77
"reflect"
88
"strconv"
99
"testing"

extra/binary_as_string_codec.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package extra
22

33
import (
44
"github.com/json-iterator/go"
5-
"unsafe"
6-
"unicode/utf8"
75
"github.com/modern-go/reflect2"
6+
"unicode/utf8"
7+
"unsafe"
88
)
99

1010
// 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
171171
func readHex(iter *jsoniter.Iterator, b1, b2 byte) byte {
172172
var ret byte
173173
if b1 >= '0' && b1 <= '9' {
174-
ret = b1-'0'
174+
ret = b1 - '0'
175175
} else if b1 >= 'a' && b1 <= 'f' {
176-
ret = b1-'a'+10
176+
ret = b1 - 'a' + 10
177177
} else {
178178
iter.ReportError("read hex", "expects 0~9 or a~f, but found "+string([]byte{b1}))
179179
return 0
180180
}
181181
ret = ret * 16
182182
if b2 >= '0' && b2 <= '9' {
183-
ret = b2-'0'
183+
ret = b2 - '0'
184184
} else if b2 >= 'a' && b2 <= 'f' {
185-
ret = b2-'a'+10
185+
ret = b2 - 'a' + 10
186186
} else {
187187
iter.ReportError("read hex", "expects 0~9 or a~f, but found "+string([]byte{b2}))
188188
return 0

extra/binary_as_string_codec_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package extra
22

33
import (
4-
"testing"
5-
"github.com/stretchr/testify/require"
64
"github.com/json-iterator/go"
5+
"github.com/stretchr/testify/require"
6+
"testing"
77
)
88

99
func init() {

misc_tests/jsoniter_map_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,14 @@ func Test_read_map_with_reader(t *testing.T) {
3131
should.Equal(m2, m1)
3232
should.Equal("1.0.76", m1["note"].(map[string]interface{})["CoreServices"].(map[string]interface{})["version_name"])
3333
}
34+
35+
func Test_map_eface_of_eface(t *testing.T) {
36+
should := require.New(t)
37+
json := jsoniter.ConfigCompatibleWithStandardLibrary
38+
output, err := json.MarshalToString(map[interface{}]interface{}{
39+
"1": 2,
40+
3: "4",
41+
})
42+
should.NoError(err)
43+
should.Equal(`{"1":2,"3":"4"}`, output)
44+
}

reflect_map.go

+22
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package jsoniter
33
import (
44
"fmt"
55
"github.com/modern-go/reflect2"
6+
"io"
67
"reflect"
78
"sort"
89
"unsafe"
@@ -107,6 +108,9 @@ func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
107108
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
108109
}
109110
}
111+
if typ.Kind() == reflect.Interface {
112+
return &dynamicMapKeyEncoder{ctx, typ}
113+
}
110114
return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
111115
}
112116
}
@@ -203,6 +207,21 @@ func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
203207
return false
204208
}
205209

210+
type dynamicMapKeyEncoder struct {
211+
ctx *ctx
212+
valType reflect2.Type
213+
}
214+
215+
func (encoder *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
216+
obj := encoder.valType.UnsafeIndirect(ptr)
217+
encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream)
218+
}
219+
220+
func (encoder *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
221+
obj := encoder.valType.UnsafeIndirect(ptr)
222+
return encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj))
223+
}
224+
206225
type mapEncoder struct {
207226
mapType *reflect2.UnsafeMapType
208227
keyEncoder ValEncoder
@@ -253,6 +272,9 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
253272
subStream.buf = make([]byte, 0, 64)
254273
key, elem := mapIter.UnsafeNext()
255274
encoder.keyEncoder.Encode(key, subStream)
275+
if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil {
276+
stream.Error = subStream.Error
277+
}
256278
encodedKey := subStream.Buffer()
257279
subIter.ResetBytes(encodedKey)
258280
decodedKey := subIter.ReadString()

value_tests/slice_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ func init() {
66
[]interface{}{"hello"},
77
nilSlice,
88
&nilSlice,
9-
selectedMarshalCase{[]byte{1,2,3}},
9+
[]byte{1, 2, 3},
1010
)
1111
unmarshalCases = append(unmarshalCases, unmarshalCase{
1212
ptr: (*[]string)(nil),
@@ -20,6 +20,5 @@ func init() {
2020
}, unmarshalCase{
2121
ptr: (*[]byte)(nil),
2222
input: `"aGVsbG8="`,
23-
selected: true,
2423
})
2524
}

value_tests/value_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import (
44
"encoding/json"
55
"fmt"
66
"github.com/json-iterator/go"
7-
"github.com/stretchr/testify/require"
87
"github.com/modern-go/reflect2"
8+
"github.com/stretchr/testify/require"
99
"testing"
1010
)
1111

0 commit comments

Comments
 (0)