1
0
mirror of https://github.com/json-iterator/go.git synced 2025-05-16 21:45:43 +02:00

fix #242 add CreateMapKeyEncoder and CreateMapKeyDecoder to extension spi

This commit is contained in:
Tao Wen 2018-02-24 22:04:11 +08:00
parent a377e2656b
commit 8d6662b81b
3 changed files with 93 additions and 0 deletions

View File

@ -6,6 +6,8 @@ import (
"testing"
"github.com/stretchr/testify/require"
"github.com/json-iterator/go"
"github.com/v2pro/plz/reflect2"
"reflect"
)
type TestObject1 struct {
@ -46,6 +48,53 @@ func Test_customize_field_by_extension(t *testing.T) {
should.Equal(`{"field-1":100}`, str)
}
func Test_customize_map_key_encoder(t *testing.T) {
should := require.New(t)
cfg := jsoniter.Config{}.Froze()
cfg.RegisterExtension(&testMapKeyExtension{})
m := map[int]int{1: 2}
output, err := cfg.MarshalToString(m)
should.NoError(err)
should.Equal(`{"2":2}`, output)
m = map[int]int{}
should.NoError(cfg.UnmarshalFromString(output, &m))
should.Equal(map[int]int{1: 2}, m)
}
type testMapKeyExtension struct {
jsoniter.DummyExtension
}
func (extension *testMapKeyExtension) CreateMapKeyEncoder(typ reflect2.Type) jsoniter.ValEncoder {
if typ.Kind() == reflect.Int {
return &funcEncoder{
fun: func(ptr unsafe.Pointer, stream *jsoniter.Stream) {
stream.WriteRaw(`"`)
stream.WriteInt(*(*int)(ptr) + 1)
stream.WriteRaw(`"`)
},
}
}
return nil
}
func (extension *testMapKeyExtension) CreateMapKeyDecoder(typ reflect2.Type) jsoniter.ValDecoder {
if typ.Kind() == reflect.Int {
return &funcDecoder{
fun: func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
i, err := strconv.Atoi(iter.ReadString())
if err != nil {
iter.ReportError("read map key", err.Error())
return
}
i--
*(*int)(ptr) = i
},
}
}
return nil
}
type funcDecoder struct {
fun jsoniter.DecoderFunc
}

View File

@ -47,6 +47,8 @@ type Binding struct {
// Can also rename fields by UpdateStructDescriptor.
type Extension interface {
UpdateStructDescriptor(structDescriptor *StructDescriptor)
CreateMapKeyDecoder(typ reflect2.Type) ValDecoder
CreateMapKeyEncoder(typ reflect2.Type) ValEncoder
CreateDecoder(typ reflect2.Type) ValDecoder
CreateEncoder(typ reflect2.Type) ValEncoder
DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder
@ -61,6 +63,16 @@ type DummyExtension struct {
func (extension *DummyExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) {
}
// CreateMapKeyDecoder No-op
func (extension *DummyExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder {
return nil
}
// CreateMapKeyEncoder No-op
func (extension *DummyExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder {
return nil
}
// CreateDecoder No-op
func (extension *DummyExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
return nil
@ -97,6 +109,16 @@ func (extension EncoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder {
return extension[typ]
}
// CreateMapKeyDecoder No-op
func (extension EncoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder {
return nil
}
// CreateMapKeyEncoder No-op
func (extension EncoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder {
return nil
}
// DecorateDecoder No-op
func (extension EncoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder {
return decoder
@ -113,6 +135,16 @@ type DecoderExtension map[reflect2.Type]ValDecoder
func (extension DecoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) {
}
// CreateMapKeyDecoder No-op
func (extension DecoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder {
return nil
}
// CreateMapKeyEncoder No-op
func (extension DecoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder {
return nil
}
// CreateDecoder get decoder from map
func (extension DecoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
return extension[typ]

View File

@ -38,6 +38,12 @@ func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder {
}
func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
for _, extension := range ctx.extensions {
decoder := extension.CreateMapKeyDecoder(typ)
if decoder != nil {
return decoder
}
}
switch typ.Kind() {
case reflect.String:
return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
@ -70,6 +76,12 @@ func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
}
func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
for _, extension := range ctx.extensions {
encoder := extension.CreateMapKeyEncoder(typ)
if encoder != nil {
return encoder
}
}
switch typ.Kind() {
case reflect.String:
return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))