github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_encoder_json_marshaler_test.go (about) 1 package jzon 2 3 import ( 4 "encoding/json" 5 "errors" 6 "reflect" 7 "testing" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestValEncoder_JsonMarshaler_Error(t *testing.T) { 13 t.Run("chain error", func(t *testing.T) { 14 t.Run("", func(t *testing.T) { 15 testStreamerChainError(t, func(s *Streamer) { 16 (*jsonMarshalerEncoder)(nil).Encode(nil, s, nil) 17 }) 18 }) 19 t.Run("dynamic", func(t *testing.T) { 20 testStreamerChainError(t, func(s *Streamer) { 21 (*dynamicJSONMarshalerEncoder)(nil).Encode(nil, s, nil) 22 }) 23 }) 24 }) 25 } 26 27 func TestValEncoder_JsonMarshaler_NonPointerReceiver(t *testing.T) { 28 f := checkEncodeValueWithStandard 29 t.Run("non pointer", func(t *testing.T) { 30 t.Run("no error", func(t *testing.T) { 31 f(t, testJSONMarshaler{ 32 data: `{"a":1}`, 33 }, nil) 34 }) 35 t.Run("error", func(t *testing.T) { 36 e := errors.New("test") 37 f(t, testJSONMarshaler{ 38 data: `{"a":1}`, 39 err: e, 40 }, e) 41 }) 42 }) 43 t.Run("pointer", func(t *testing.T) { 44 t.Run("nil", func(t *testing.T) { 45 f(t, (*testJSONMarshaler)(nil), nil) 46 }) 47 t.Run("no error", func(t *testing.T) { 48 f(t, &testJSONMarshaler{ 49 data: `{"a":2}`, 50 }, nil) 51 }) 52 t.Run("error", func(t *testing.T) { 53 e := errors.New("test") 54 f(t, &testJSONMarshaler{ 55 data: `{"a":2}`, 56 err: e, 57 }, e) 58 }) 59 }) 60 t.Run("pointer of pointer", func(t *testing.T) { 61 t.Run("nil", func(t *testing.T) { 62 f(t, (**testJSONMarshaler)(nil), nil) 63 }) 64 t.Run("pointer of nil", func(t *testing.T) { 65 ptr := (*testJSONMarshaler)(nil) 66 f(t, &ptr, nil) 67 }) 68 t.Run("no error", func(t *testing.T) { 69 ptr := &testJSONMarshaler{ 70 data: `{"a":2}`, 71 } 72 f(t, &ptr, nil) 73 }) 74 t.Run("error", func(t *testing.T) { 75 e := errors.New("test") 76 ptr := &testJSONMarshaler{ 77 data: `{"a":2}`, 78 err: e, 79 } 80 f(t, &ptr, e) 81 }) 82 }) 83 } 84 85 func TestValEncoder_JsonMarshaler_PointerReceiver(t *testing.T) { 86 f := checkEncodeValueWithStandard 87 t.Run("non pointer", func(t *testing.T) { 88 t.Run("no error", func(t *testing.T) { 89 f(t, testJSONMarshaler2{ 90 data: `{"b":1}`, 91 }, nil) 92 }) 93 t.Run("error", func(t *testing.T) { 94 e := errors.New("test") 95 f(t, testJSONMarshaler2{ 96 data: `{"b":1}`, 97 err: e, 98 }, nil) 99 }) 100 }) 101 t.Run("pointer", func(t *testing.T) { 102 t.Run("nil", func(t *testing.T) { 103 f(t, (*testJSONMarshaler2)(nil), nil) 104 }) 105 t.Run("no error", func(t *testing.T) { 106 f(t, &testJSONMarshaler2{ 107 data: `{"b":1}`, 108 }, nil) 109 }) 110 t.Run("error", func(t *testing.T) { 111 e := errors.New("test") 112 f(t, &testJSONMarshaler2{ 113 data: `{"b":1}`, 114 err: e, 115 }, e) 116 }) 117 }) 118 t.Run("pointer of pointer", func(t *testing.T) { 119 t.Run("nil", func(t *testing.T) { 120 f(t, (**testJSONMarshaler2)(nil), nil) 121 }) 122 t.Run("pointer of nil", func(t *testing.T) { 123 ptr := (*testJSONMarshaler2)(nil) 124 f(t, &ptr, nil) 125 }) 126 t.Run("no error", func(t *testing.T) { 127 ptr := &testJSONMarshaler2{ 128 data: `{"a":2}`, 129 } 130 f(t, &ptr, nil) 131 }) 132 t.Run("error", func(t *testing.T) { 133 e := errors.New("test") 134 ptr := &testJSONMarshaler2{ 135 data: `{"a":2}`, 136 err: e, 137 } 138 f(t, &ptr, e) 139 }) 140 }) 141 t.Run("struct member", func(t *testing.T) { 142 t.Run("value", func(t *testing.T) { 143 type st struct { 144 A testJSONMarshaler2 145 } 146 /* 147 * with the current implementation, 148 * only one of the following two test can succeed 149 */ 150 t.Run("value", func(t *testing.T) { 151 skipTest(t, "pointer encoder on value") 152 checkEncodeValueWithStandard(t, st{ 153 A: testJSONMarshaler2{ 154 data: `{"a":2}`, 155 }, 156 }, nil) 157 }) 158 t.Run("ptr", func(t *testing.T) { 159 checkEncodeValueWithStandard(t, &st{ 160 A: testJSONMarshaler2{ 161 data: `{"a":2}`, 162 }, 163 }, nil) 164 }) 165 }) 166 t.Run("pointer", func(t *testing.T) { 167 type st struct { 168 A *testJSONMarshaler2 169 } 170 t.Run("nil", func(t *testing.T) { 171 checkEncodeValueWithStandard(t, &st{}, nil) 172 }) 173 }) 174 }) 175 } 176 177 func TestValEncoder_DynamicJsonMarshaler(t *testing.T) { 178 t.Run("marshaler nil", func(t *testing.T) { 179 var i json.Marshaler 180 checkEncodeValueWithStandard(t, &i, nil) 181 }) 182 t.Run("marshaler error", func(t *testing.T) { 183 e := errors.New("test") 184 var i json.Marshaler = testJSONMarshaler{ 185 data: `"test"`, 186 err: e, 187 } 188 checkEncodeValueWithStandard(t, &i, e) 189 }) 190 t.Run("marshaler", func(t *testing.T) { 191 var i json.Marshaler = testJSONMarshaler{ 192 data: `"test"`, 193 } 194 checkEncodeValueWithStandard(t, &i, nil) 195 }) 196 t.Run("marshaler 2", func(t *testing.T) { 197 var i json.Marshaler = &testJSONMarshaler{ 198 data: `"test 2"`, 199 } 200 checkEncodeValueWithStandard(t, &i, nil) 201 }) 202 } 203 204 func TestValEncoder_JsonMarshaler_Direct(t *testing.T) { 205 t.Run("value", func(t *testing.T) { 206 t.Run("nil", func(t *testing.T) { 207 checkEncodeValueWithStandard(t, testMapJSONMarshaler(nil), nil) 208 }) 209 t.Run("non nil", func(t *testing.T) { 210 checkEncodeValueWithStandard(t, testMapJSONMarshaler{ 211 1: 2, 212 }, nil) 213 }) 214 }) 215 t.Run("pointer", func(t *testing.T) { 216 t.Run("nil", func(t *testing.T) { 217 checkEncodeValueWithStandard(t, (*testMapJSONMarshaler)(nil), nil) 218 }) 219 t.Run("non nil", func(t *testing.T) { 220 var m testMapJSONMarshaler 221 checkEncodeValueWithStandard(t, &m, nil) 222 }) 223 t.Run("non nil 2", func(t *testing.T) { 224 checkEncodeValueWithStandard(t, &testMapJSONMarshaler{ 225 1: 2, 226 }, nil) 227 }) 228 }) 229 t.Run("struct member", func(t *testing.T) { 230 type st struct { 231 A testMapJSONMarshaler 232 } 233 checkEncodeValueWithStandard(t, &st{}, nil) 234 }) 235 t.Run("value of marshaler", func(t *testing.T) { 236 t.Run("nil", func(t *testing.T) { 237 var m json.Marshaler 238 checkEncodeValueWithStandard(t, m, nil) 239 }) 240 t.Run("value", func(t *testing.T) { 241 var m json.Marshaler = testMapJSONMarshaler{ 242 1: 2, 243 } 244 checkEncodeValueWithStandard(t, m, nil) 245 }) 246 t.Run("pointer", func(t *testing.T) { 247 var m json.Marshaler = &testMapJSONMarshaler{ 248 1: 2, 249 } 250 checkEncodeValueWithStandard(t, m, nil) 251 }) 252 }) 253 t.Run("pointer of marshaler", func(t *testing.T) { 254 t.Run("nil", func(t *testing.T) { 255 var m json.Marshaler 256 checkEncodeValueWithStandard(t, &m, nil) 257 }) 258 t.Run("value", func(t *testing.T) { 259 var m json.Marshaler = testMapJSONMarshaler{ 260 1: 2, 261 } 262 checkEncodeValueWithStandard(t, &m, nil) 263 }) 264 t.Run("pointer", func(t *testing.T) { 265 var m json.Marshaler = &testMapJSONMarshaler{ 266 1: 2, 267 } 268 checkEncodeValueWithStandard(t, &m, nil) 269 }) 270 }) 271 } 272 273 func TestValEncoder_JsonMarshaler_OmitEmpty(t *testing.T) { 274 t.Run("json marshaler", func(t *testing.T) { 275 type st struct { 276 A testJSONMarshaler `json:",omitempty"` 277 } 278 checkEncodeValueWithStandard(t, st{ 279 A: testJSONMarshaler{ 280 data: "true", 281 }, 282 }, nil) 283 }) 284 t.Run("indirect json marshaler", func(t *testing.T) { 285 t.Run("bool", func(t *testing.T) { 286 type st struct { 287 A testBoolJSONMarshaler `json:",omitempty"` 288 } 289 require.True(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type))) 290 checkEncodeValueWithStandard(t, st{ 291 A: true, 292 }, nil) 293 checkEncodeValueWithStandard(t, st{ 294 A: false, 295 }, nil) 296 }) 297 t.Run("array", func(t *testing.T) { 298 type st struct { 299 A testIndirectArrayMarshaler `json:",omitempty"` 300 } 301 require.True(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type))) 302 checkEncodeValueWithStandard(t, st{}, nil) 303 checkEncodeValueWithStandard(t, st{ 304 A: testIndirectArrayMarshaler{2}, 305 }, nil) 306 }) 307 t.Run("slice", func(t *testing.T) { 308 type st struct { 309 A testSliceMarshaler `json:",omitempty"` 310 } 311 require.True(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type))) 312 t.Run("nil", func(t *testing.T) { 313 checkEncodeValueWithStandard(t, st{}, nil) 314 }) 315 t.Run("empty", func(t *testing.T) { 316 checkEncodeValueWithStandard(t, st{ 317 A: testSliceMarshaler{}, 318 }, nil) 319 }) 320 t.Run("non empty", func(t *testing.T) { 321 checkEncodeValueWithStandard(t, st{ 322 A: testSliceMarshaler{4, 5, 6}, 323 }, nil) 324 }) 325 }) 326 t.Run("struct", func(t *testing.T) { 327 type st struct { 328 A testIndirectStructMarshaler `json:",omitempty"` 329 } 330 require.True(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type))) 331 checkEncodeValueWithStandard(t, st{}, nil) 332 checkEncodeValueWithStandard(t, st{ 333 A: testIndirectStructMarshaler{1}, 334 }, nil) 335 }) 336 }) 337 t.Run("direct json marshaler", func(t *testing.T) { 338 t.Run("array", func(t *testing.T) { 339 type st struct { 340 A testDirectArrayMarshaler `json:",omitempty"` 341 } 342 require.False(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type))) 343 checkEncodeValueWithStandard(t, st{}, nil) 344 i := 123 345 checkEncodeValueWithStandard(t, st{ 346 A: testDirectArrayMarshaler{&i}, 347 }, nil) 348 }) 349 t.Run("map", func(t *testing.T) { 350 type st struct { 351 A testMapJSONMarshaler `json:",omitempty"` 352 } 353 require.False(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type))) 354 t.Run("nil", func(t *testing.T) { 355 checkEncodeValueWithStandard(t, st{}, nil) 356 }) 357 t.Run("zero", func(t *testing.T) { 358 checkEncodeValueWithStandard(t, st{ 359 A: testMapJSONMarshaler{}, 360 }, nil) 361 }) 362 t.Run("non zero", func(t *testing.T) { 363 checkEncodeValueWithStandard(t, st{ 364 A: testMapJSONMarshaler{1: 2}, 365 }, nil) 366 }) 367 }) 368 t.Run("struct", func(t *testing.T) { 369 type st struct { 370 A testDirectStructMarshaler `json:",omitempty"` 371 } 372 require.False(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type))) 373 checkEncodeValueWithStandard(t, st{}, nil) 374 i := 2 375 checkEncodeValueWithStandard(t, st{ 376 A: testDirectStructMarshaler{&i}, 377 }, nil) 378 }) 379 }) 380 t.Run("pointer json marshaler", func(t *testing.T) { 381 t.Run("value field", func(t *testing.T) { 382 type st struct { 383 A testJSONMarshaler2 `json:",omitempty"` 384 } 385 t.Run("no data", func(t *testing.T) { 386 skipTest(t, "incompatible with std") 387 checkEncodeValueWithStandard(t, &st{ 388 A: testJSONMarshaler2{}, 389 }, nil) 390 }) 391 t.Run("with data", func(t *testing.T) { 392 checkEncodeValueWithStandard(t, &st{ 393 A: testJSONMarshaler2{ 394 data: "true", 395 }, 396 }, nil) 397 }) 398 }) 399 t.Run("pointer field", func(t *testing.T) { 400 type st struct { 401 A *testJSONMarshaler2 `json:",omitempty"` 402 } 403 t.Run("nil", func(t *testing.T) { 404 skipTest(t, "incompatible with std") 405 checkEncodeValueWithStandard(t, &st{}, nil) 406 }) 407 t.Run("no data", func(t *testing.T) { 408 skipTest(t, "incompatible with std") 409 checkEncodeValueWithStandard(t, &st{ 410 A: &testJSONMarshaler2{}, 411 }, nil) 412 }) 413 t.Run("with data", func(t *testing.T) { 414 checkEncodeValueWithStandard(t, &st{ 415 A: &testJSONMarshaler2{ 416 data: "true", 417 }, 418 }, nil) 419 }) 420 }) 421 422 }) 423 t.Run("dynamic json marshaler", func(t *testing.T) { 424 type st struct { 425 A json.Marshaler `json:",omitempty"` 426 } 427 t.Run("nil", func(t *testing.T) { 428 checkEncodeValueWithStandard(t, st{}, nil) 429 }) 430 t.Run("nil pointer", func(t *testing.T) { 431 checkEncodeValueWithStandard(t, st{ 432 A: (*testJSONMarshaler2)(nil), 433 }, nil) 434 }) 435 }) 436 }