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