Skip to content

Commit 8d6662b

Browse files
committed
fix json-iterator#242 add CreateMapKeyEncoder and CreateMapKeyDecoder to extension spi
1 parent a377e26 commit 8d6662b

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

extension_tests/extension_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"testing"
77
"github.com/stretchr/testify/require"
88
"github.com/json-iterator/go"
9+
"github.com/v2pro/plz/reflect2"
10+
"reflect"
911
)
1012

1113
type TestObject1 struct {
@@ -46,6 +48,53 @@ func Test_customize_field_by_extension(t *testing.T) {
4648
should.Equal(`{"field-1":100}`, str)
4749
}
4850

51+
func Test_customize_map_key_encoder(t *testing.T) {
52+
should := require.New(t)
53+
cfg := jsoniter.Config{}.Froze()
54+
cfg.RegisterExtension(&testMapKeyExtension{})
55+
m := map[int]int{1: 2}
56+
output, err := cfg.MarshalToString(m)
57+
should.NoError(err)
58+
should.Equal(`{"2":2}`, output)
59+
m = map[int]int{}
60+
should.NoError(cfg.UnmarshalFromString(output, &m))
61+
should.Equal(map[int]int{1: 2}, m)
62+
}
63+
64+
type testMapKeyExtension struct {
65+
jsoniter.DummyExtension
66+
}
67+
68+
func (extension *testMapKeyExtension) CreateMapKeyEncoder(typ reflect2.Type) jsoniter.ValEncoder {
69+
if typ.Kind() == reflect.Int {
70+
return &funcEncoder{
71+
fun: func(ptr unsafe.Pointer, stream *jsoniter.Stream) {
72+
stream.WriteRaw(`"`)
73+
stream.WriteInt(*(*int)(ptr) + 1)
74+
stream.WriteRaw(`"`)
75+
},
76+
}
77+
}
78+
return nil
79+
}
80+
81+
func (extension *testMapKeyExtension) CreateMapKeyDecoder(typ reflect2.Type) jsoniter.ValDecoder {
82+
if typ.Kind() == reflect.Int {
83+
return &funcDecoder{
84+
fun: func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
85+
i, err := strconv.Atoi(iter.ReadString())
86+
if err != nil {
87+
iter.ReportError("read map key", err.Error())
88+
return
89+
}
90+
i--
91+
*(*int)(ptr) = i
92+
},
93+
}
94+
}
95+
return nil
96+
}
97+
4998
type funcDecoder struct {
5099
fun jsoniter.DecoderFunc
51100
}

reflect_extension.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ type Binding struct {
4747
// Can also rename fields by UpdateStructDescriptor.
4848
type Extension interface {
4949
UpdateStructDescriptor(structDescriptor *StructDescriptor)
50+
CreateMapKeyDecoder(typ reflect2.Type) ValDecoder
51+
CreateMapKeyEncoder(typ reflect2.Type) ValEncoder
5052
CreateDecoder(typ reflect2.Type) ValDecoder
5153
CreateEncoder(typ reflect2.Type) ValEncoder
5254
DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder
@@ -61,6 +63,16 @@ type DummyExtension struct {
6163
func (extension *DummyExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) {
6264
}
6365

66+
// CreateMapKeyDecoder No-op
67+
func (extension *DummyExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder {
68+
return nil
69+
}
70+
71+
// CreateMapKeyEncoder No-op
72+
func (extension *DummyExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder {
73+
return nil
74+
}
75+
6476
// CreateDecoder No-op
6577
func (extension *DummyExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
6678
return nil
@@ -97,6 +109,16 @@ func (extension EncoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder {
97109
return extension[typ]
98110
}
99111

112+
// CreateMapKeyDecoder No-op
113+
func (extension EncoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder {
114+
return nil
115+
}
116+
117+
// CreateMapKeyEncoder No-op
118+
func (extension EncoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder {
119+
return nil
120+
}
121+
100122
// DecorateDecoder No-op
101123
func (extension EncoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder {
102124
return decoder
@@ -113,6 +135,16 @@ type DecoderExtension map[reflect2.Type]ValDecoder
113135
func (extension DecoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) {
114136
}
115137

138+
// CreateMapKeyDecoder No-op
139+
func (extension DecoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder {
140+
return nil
141+
}
142+
143+
// CreateMapKeyEncoder No-op
144+
func (extension DecoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder {
145+
return nil
146+
}
147+
116148
// CreateDecoder get decoder from map
117149
func (extension DecoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
118150
return extension[typ]

reflect_map.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder {
3838
}
3939

4040
func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
41+
for _, extension := range ctx.extensions {
42+
decoder := extension.CreateMapKeyDecoder(typ)
43+
if decoder != nil {
44+
return decoder
45+
}
46+
}
4147
switch typ.Kind() {
4248
case reflect.String:
4349
return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
@@ -70,6 +76,12 @@ func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
7076
}
7177

7278
func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
79+
for _, extension := range ctx.extensions {
80+
encoder := extension.CreateMapKeyEncoder(typ)
81+
if encoder != nil {
82+
return encoder
83+
}
84+
}
7385
switch typ.Kind() {
7486
case reflect.String:
7587
return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))

0 commit comments

Comments
 (0)