1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-20 11:28:49 +02:00

suport encode map[interface{}]interface{}

This commit is contained in:
Tao Wen 2018-03-15 21:28:16 +08:00
parent 39acec93e0
commit ca39e5af3e
8 changed files with 46 additions and 15 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -31,3 +31,14 @@ func Test_read_map_with_reader(t *testing.T) {
should.Equal(m2, m1) should.Equal(m2, m1)
should.Equal("1.0.76", m1["note"].(map[string]interface{})["CoreServices"].(map[string]interface{})["version_name"]) 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)
}

View File

@ -3,6 +3,7 @@ package jsoniter
import ( import (
"fmt" "fmt"
"github.com/modern-go/reflect2" "github.com/modern-go/reflect2"
"io"
"reflect" "reflect"
"sort" "sort"
"unsafe" "unsafe"
@ -107,6 +108,9 @@ func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), 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)} 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 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 { type mapEncoder struct {
mapType *reflect2.UnsafeMapType mapType *reflect2.UnsafeMapType
keyEncoder ValEncoder keyEncoder ValEncoder
@ -253,6 +272,9 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
subStream.buf = make([]byte, 0, 64) subStream.buf = make([]byte, 0, 64)
key, elem := mapIter.UnsafeNext() key, elem := mapIter.UnsafeNext()
encoder.keyEncoder.Encode(key, subStream) encoder.keyEncoder.Encode(key, subStream)
if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil {
stream.Error = subStream.Error
}
encodedKey := subStream.Buffer() encodedKey := subStream.Buffer()
subIter.ResetBytes(encodedKey) subIter.ResetBytes(encodedKey)
decodedKey := subIter.ReadString() decodedKey := subIter.ReadString()

View File

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

View File

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