...
1 package test
2
3 import (
4 "github.com/json-iterator/go"
5 "github.com/modern-go/reflect2"
6 "github.com/stretchr/testify/require"
7 "reflect"
8 "strconv"
9 "testing"
10 "unsafe"
11 )
12
13 type TestObject1 struct {
14 Field1 string
15 }
16
17 type testExtension struct {
18 jsoniter.DummyExtension
19 }
20
21 func (extension *testExtension) UpdateStructDescriptor(structDescriptor *jsoniter.StructDescriptor) {
22 if structDescriptor.Type.String() != "test.TestObject1" {
23 return
24 }
25 binding := structDescriptor.GetField("Field1")
26 binding.Encoder = &funcEncoder{fun: func(ptr unsafe.Pointer, stream *jsoniter.Stream) {
27 str := *((*string)(ptr))
28 val, _ := strconv.Atoi(str)
29 stream.WriteInt(val)
30 }}
31 binding.Decoder = &funcDecoder{func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
32 *((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
33 }}
34 binding.ToNames = []string{"field-1"}
35 binding.FromNames = []string{"field-1"}
36 }
37
38 func Test_customize_field_by_extension(t *testing.T) {
39 should := require.New(t)
40 cfg := jsoniter.Config{}.Froze()
41 cfg.RegisterExtension(&testExtension{})
42 obj := TestObject1{}
43 err := cfg.UnmarshalFromString(`{"field-1": 100}`, &obj)
44 should.Nil(err)
45 should.Equal("100", obj.Field1)
46 str, err := cfg.MarshalToString(obj)
47 should.Nil(err)
48 should.Equal(`{"field-1":100}`, str)
49 }
50
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
98 type funcDecoder struct {
99 fun jsoniter.DecoderFunc
100 }
101
102 func (decoder *funcDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
103 decoder.fun(ptr, iter)
104 }
105
106 type funcEncoder struct {
107 fun jsoniter.EncoderFunc
108 isEmptyFunc func(ptr unsafe.Pointer) bool
109 }
110
111 func (encoder *funcEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
112 encoder.fun(ptr, stream)
113 }
114
115 func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool {
116 if encoder.isEmptyFunc == nil {
117 return false
118 }
119 return encoder.isEmptyFunc(ptr)
120 }
121
View as plain text