github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/decoder_config_test.go (about) 1 package jzon 2 3 import ( 4 "reflect" 5 "runtime/debug" 6 "testing" 7 "unsafe" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 type testIntDecoder struct{} 13 14 func (*testIntDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error { 15 vt, err := it.NextValueType() 16 if err != nil { 17 return err 18 } 19 switch vt { 20 case NullValue: 21 if err := it.ReadNull(); err != nil { 22 return err 23 } 24 *(*int)(ptr) = 1 25 return nil 26 default: 27 i, err := it.ReadInt() 28 if err != nil { 29 return err 30 } 31 *(*int)(ptr) = i * 2 32 return nil 33 } 34 } 35 36 type testPtrDecoder struct{} 37 38 func (*testPtrDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error { 39 vt, err := it.NextValueType() 40 if err != nil { 41 return err 42 } 43 switch vt { 44 case NullValue: 45 if err := it.ReadNull(); err != nil { 46 return err 47 } 48 v := -1 49 *(**int)(ptr) = &v 50 return nil 51 default: 52 i, err := it.ReadInt() 53 if err != nil { 54 return err 55 } 56 i = i * 2 57 *(**int)(ptr) = &i 58 return nil 59 } 60 } 61 62 func TestDecoderConfig_CustomConfig(t *testing.T) { 63 t.Run("int", func(t *testing.T) { 64 decCfg := NewDecoderConfig(&DecoderOption{ 65 ValDecoders: map[reflect.Type]ValDecoder{ 66 reflect.TypeOf(int(0)): (*testIntDecoder)(nil), 67 }, 68 CaseSensitive: true, 69 }) 70 t.Run("value", func(t *testing.T) { 71 t.Run("null", func(t *testing.T) { 72 var i int 73 err := decCfg.UnmarshalFromString("null", &i) 74 require.NoError(t, err) 75 require.Equal(t, 1, i) 76 }) 77 t.Run("not null", func(t *testing.T) { 78 var i int 79 err := decCfg.UnmarshalFromString("1", &i) 80 require.NoError(t, err) 81 require.Equal(t, 2, i) 82 }) 83 }) 84 t.Run("pointer", func(t *testing.T) { 85 t.Run("null on not null", func(t *testing.T) { 86 v := 1 87 i := &v 88 err := decCfg.UnmarshalFromString("null", &i) 89 require.NoError(t, err) 90 require.Nil(t, i) 91 }) 92 t.Run("not null", func(t *testing.T) { 93 v := -1 94 i := &v 95 err := decCfg.UnmarshalFromString("2", &i) 96 require.NoError(t, err) 97 require.NotNil(t, i) 98 require.Equal(t, 4, v) 99 }) 100 }) 101 t.Run("field", func(t *testing.T) { 102 t.Run("value", func(t *testing.T) { 103 st := struct { 104 A int `json:"a"` 105 }{} 106 t.Run("not present", func(t *testing.T) { 107 v := 1 108 st.A = v 109 err := decCfg.UnmarshalFromString(`{}`, &st) 110 require.NoError(t, err) 111 require.Equal(t, v, st.A) 112 }) 113 t.Run("null", func(t *testing.T) { 114 st.A = -1 115 err := decCfg.UnmarshalFromString(`{"a":null}`, &st) 116 require.NoError(t, err) 117 require.Equal(t, 1, st.A) 118 }) 119 t.Run("not null", func(t *testing.T) { 120 st.A = -1 121 err := decCfg.UnmarshalFromString(`{"a":1}`, &st) 122 require.NoError(t, err) 123 require.Equal(t, 2, st.A) 124 }) 125 }) 126 t.Run("pointer", func(t *testing.T) { 127 st := struct { 128 A *int `json:"a"` 129 }{} 130 t.Run("not present", func(t *testing.T) { 131 v := 123 132 st.A = &v 133 err := decCfg.UnmarshalFromString(`{}`, &st) 134 require.NoError(t, err) 135 require.Equal(t, &v, st.A) 136 }) 137 t.Run("null on not null", func(t *testing.T) { 138 v := 123 139 st.A = &v 140 err := decCfg.UnmarshalFromString(`{"a":null}`, &st) 141 require.NoError(t, err) 142 require.Nil(t, st.A) 143 }) 144 t.Run("not null", func(t *testing.T) { 145 v := 123 146 st.A = &v 147 err := decCfg.UnmarshalFromString(`{"a":1}`, &st) 148 require.NoError(t, err) 149 require.NotNil(t, st.A) 150 require.Equal(t, 2, *st.A) 151 }) 152 }) 153 }) 154 }) 155 t.Run("ptr", func(t *testing.T) { 156 decCfg := NewDecoderConfig(&DecoderOption{ 157 ValDecoders: map[reflect.Type]ValDecoder{ 158 reflect.TypeOf((*int)(nil)): (*testPtrDecoder)(nil), 159 }, 160 CaseSensitive: true, 161 }) 162 t.Run("value", func(t *testing.T) { 163 t.Run("null", func(t *testing.T) { 164 var i *int 165 err := decCfg.UnmarshalFromString("null", &i) 166 require.NoError(t, err) 167 require.NotNil(t, i) 168 require.Equal(t, -1, *i) 169 }) 170 t.Run("not null", func(t *testing.T) { 171 var i *int 172 err := decCfg.UnmarshalFromString("1", &i) 173 require.NoError(t, err) 174 require.NotNil(t, i) 175 require.Equal(t, 2, *i) 176 }) 177 }) 178 t.Run("struct", func(t *testing.T) { 179 t.Run("value", func(t *testing.T) { 180 st := struct { 181 A *int `json:"a"` 182 }{} 183 t.Run("null", func(t *testing.T) { 184 i := 123 185 st.A = &i 186 err := decCfg.UnmarshalFromString("null", &st) 187 require.NoError(t, err) 188 require.Equal(t, &i, st.A) 189 }) 190 t.Run("not present", func(t *testing.T) { 191 i := 123 192 st.A = &i 193 err := decCfg.UnmarshalFromString(`{}`, &st) 194 require.NoError(t, err) 195 require.Equal(t, &i, st.A) 196 }) 197 t.Run("present as null", func(t *testing.T) { 198 i := 123 199 st.A = &i 200 err := decCfg.UnmarshalFromString(`{"a":null}`, &st) 201 require.NoError(t, err) 202 require.NotNil(t, st.A) 203 require.Equal(t, -1, *st.A) 204 }) 205 t.Run("present as not null", func(t *testing.T) { 206 i := 123 207 st.A = &i 208 err := decCfg.UnmarshalFromString(`{"a":1}`, &st) 209 require.NoError(t, err) 210 require.NotNil(t, st.A) 211 require.Equal(t, 2, *st.A) 212 }) 213 }) 214 t.Run("pointer", func(t *testing.T) { 215 st := struct { 216 A **int `json:"a"` 217 }{} 218 var v *int 219 st.A = &v 220 require.NotNil(t, st.A) 221 err := decCfg.UnmarshalFromString(`{"a":null}`, &st) 222 require.NoError(t, err) 223 require.Nil(t, st.A) 224 }) 225 }) 226 }) 227 debug.FreeOSMemory() 228 }