encode_object_test.go (23932B)
1 package gojay 2 3 import ( 4 "strings" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 ) 10 11 type testObjectWithUnknownType struct { 12 unknownType struct{} 13 } 14 15 func (t *testObjectWithUnknownType) IsNil() bool { 16 return t == nil 17 } 18 19 func (t *testObjectWithUnknownType) MarshalJSONObject(enc *Encoder) { 20 enc.AddInterfaceKey("unknownType", t.unknownType) 21 } 22 23 type TestEncoding struct { 24 test string 25 test2 string 26 testInt int 27 testBool bool 28 testF32 float32 29 testF64 float64 30 testInterface interface{} 31 testArr TestEncodingArr 32 sub *SubObject 33 } 34 35 func (t *TestEncoding) IsNil() bool { 36 return t == nil 37 } 38 39 func (t *TestEncoding) MarshalJSONObject(enc *Encoder) { 40 enc.AddStringKey("test", t.test) 41 enc.AddStringKey("test2", t.test2) 42 enc.AddIntKey("testInt", t.testInt) 43 enc.AddBoolKey("testBool", t.testBool) 44 enc.AddInterfaceKey("testArr", t.testArr) 45 enc.AddInterfaceKey("testF64", t.testF64) 46 enc.AddInterfaceKey("testF32", t.testF32) 47 enc.AddInterfaceKey("testInterface", t.testInterface) 48 enc.AddInterfaceKey("sub", t.sub) 49 } 50 51 type SubObject struct { 52 test1 int 53 test2 string 54 test3 float64 55 testBool bool 56 sub *SubObject 57 } 58 59 func (t *SubObject) IsNil() bool { 60 return t == nil 61 } 62 63 func (t *SubObject) MarshalJSONObject(enc *Encoder) { 64 enc.AddIntKey("test1", t.test1) 65 enc.AddStringKey("test2", t.test2) 66 enc.AddFloatKey("test3", t.test3) 67 enc.AddBoolKey("testBool", t.testBool) 68 enc.AddObjectKey("sub", t.sub) 69 } 70 71 type testEncodingObjInterfaces struct { 72 interfaceVal interface{} 73 } 74 75 func (t *testEncodingObjInterfaces) IsNil() bool { 76 return t == nil 77 } 78 79 func (t *testEncodingObjInterfaces) MarshalJSONObject(enc *Encoder) { 80 enc.AddInterfaceKey("interfaceVal", t.interfaceVal) 81 } 82 83 func TestEncoderObjectEncodeAPI(t *testing.T) { 84 t.Run("encode-basic", func(t *testing.T) { 85 builder := &strings.Builder{} 86 enc := NewEncoder(builder) 87 err := enc.EncodeObject(&testObject{ 88 "漢字", nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil, 89 1, nil, 1, nil, 1.1, nil, 1.1, nil, true, nil, 90 &testObject{}, testSliceInts{}, interface{}("test"), 91 }) 92 assert.Nil(t, err, "Error should be nil") 93 assert.Equal( 94 t, 95 `{"testStr":"漢字","testInt":1,"testInt64":1,"testInt32":1,"testInt16":1,"testInt8":1,"testUint64":1,"testUint32":1,"testUint16":1,"testUint8":1,"testFloat64":1.1,"testFloat32":1.1,"testBool":true}`, 96 builder.String(), 97 "Result of marshalling is different as the one expected", 98 ) 99 }) 100 } 101 102 func TestEncoderObjectMarshalAPI(t *testing.T) { 103 t.Run("marshal-basic", func(t *testing.T) { 104 r, err := Marshal(&testObject{ 105 "漢字", nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, 106 nil, 1, nil, 1, nil, 1.1, nil, 1.1, nil, true, nil, 107 &testObject{}, testSliceInts{}, []interface{}{"h", "o", "l", "a"}, 108 }) 109 assert.Nil(t, err, "Error should be nil") 110 assert.Equal( 111 t, 112 `{"testStr":"漢字","testInt":1,"testInt64":1,"testInt32":1,"testInt16":1,"testInt8":1,"testUint64":1,"testUint32":1,"testUint16":1,"testUint8":1,"testFloat64":1.1,"testFloat32":1.1,"testBool":true}`, 113 string(r), 114 "Result of marshalling is different as the one expected", 115 ) 116 }) 117 118 t.Run("marshal-complex", func(t *testing.T) { 119 v := &TestEncoding{ 120 test: "hello world", 121 test2: "foobar", 122 testInt: 1, 123 testBool: true, 124 testF32: 120.53, 125 testF64: 120.15, 126 testInterface: true, 127 testArr: TestEncodingArr{ 128 &TestEncoding{ 129 test: "1", 130 }, 131 }, 132 sub: &SubObject{ 133 test1: 10, 134 test2: "hello world", 135 test3: 1.23543, 136 testBool: true, 137 sub: &SubObject{ 138 test1: 10, 139 testBool: false, 140 test2: "hello world", 141 }, 142 }, 143 } 144 r, err := MarshalJSONObject(v) 145 assert.Nil(t, err, "Error should be nil") 146 assert.Equal( 147 t, 148 `{"test":"hello world","test2":"foobar","testInt":1,"testBool":true,"testArr":[{"test":"1","test2":"","testInt":0,"testBool":false,"testArr":[],"testF64":0,"testF32":0,"sub":{}}],"testF64":120.15,"testF32":120.53,"testInterface":true,"sub":{"test1":10,"test2":"hello world","test3":1.23543,"testBool":true,"sub":{"test1":10,"test2":"hello world","test3":0,"testBool":false,"sub":{}}}}`, 149 string(r), 150 "Result of marshalling is different as the one expected", 151 ) 152 }) 153 154 t.Run("marshal-interface-string", func(t *testing.T) { 155 v := testEncodingObjInterfaces{"string"} 156 r, err := Marshal(&v) 157 assert.Nil(t, err, "Error should be nil") 158 assert.Equal( 159 t, 160 `{"interfaceVal":"string"}`, 161 string(r), 162 "Result of marshalling is different as the one expected") 163 }) 164 t.Run("marshal-interface-int", func(t *testing.T) { 165 v := testEncodingObjInterfaces{1} 166 r, err := Marshal(&v) 167 assert.Nil(t, err, "Error should be nil") 168 assert.Equal( 169 t, 170 `{"interfaceVal":1}`, 171 string(r), 172 "Result of marshalling is different as the one expected") 173 }) 174 t.Run("marshal-interface-int64", func(t *testing.T) { 175 v := testEncodingObjInterfaces{int64(1)} 176 r, err := Marshal(&v) 177 assert.Nil(t, err, "Error should be nil") 178 assert.Equal( 179 t, 180 `{"interfaceVal":1}`, 181 string(r), 182 "Result of marshalling is different as the one expected") 183 }) 184 t.Run("marshal-interface-int32", func(t *testing.T) { 185 v := testEncodingObjInterfaces{int32(1)} 186 r, err := Marshal(&v) 187 assert.Nil(t, err, "Error should be nil") 188 assert.Equal( 189 t, 190 `{"interfaceVal":1}`, 191 string(r), 192 "Result of marshalling is different as the one expected") 193 }) 194 t.Run("marshal-interface-int16", func(t *testing.T) { 195 v := testEncodingObjInterfaces{int16(1)} 196 r, err := Marshal(&v) 197 assert.Nil(t, err, "Error should be nil") 198 assert.Equal( 199 t, 200 `{"interfaceVal":1}`, 201 string(r), 202 "Result of marshalling is different as the one expected") 203 }) 204 t.Run("marshal-interface-int8", func(t *testing.T) { 205 v := testEncodingObjInterfaces{int8(1)} 206 r, err := Marshal(&v) 207 assert.Nil(t, err, "Error should be nil") 208 assert.Equal( 209 t, 210 `{"interfaceVal":1}`, 211 string(r), 212 "Result of marshalling is different as the one expected") 213 }) 214 t.Run("marshal-interface-uint64", func(t *testing.T) { 215 v := testEncodingObjInterfaces{uint64(1)} 216 r, err := Marshal(&v) 217 assert.Nil(t, err, "Error should be nil") 218 assert.Equal( 219 t, 220 `{"interfaceVal":1}`, 221 string(r), 222 "Result of marshalling is different as the one expected") 223 }) 224 t.Run("marshal-interface-uint32", func(t *testing.T) { 225 v := testEncodingObjInterfaces{uint32(1)} 226 r, err := Marshal(&v) 227 assert.Nil(t, err, "Error should be nil") 228 assert.Equal( 229 t, 230 `{"interfaceVal":1}`, 231 string(r), 232 "Result of marshalling is different as the one expected") 233 }) 234 t.Run("marshal-interface-uint16", func(t *testing.T) { 235 v := testEncodingObjInterfaces{uint16(1)} 236 r, err := Marshal(&v) 237 assert.Nil(t, err, "Error should be nil") 238 assert.Equal( 239 t, 240 `{"interfaceVal":1}`, 241 string(r), 242 "Result of marshalling is different as the one expected") 243 }) 244 t.Run("marshal-interface-uint8", func(t *testing.T) { 245 v := testEncodingObjInterfaces{uint8(1)} 246 r, err := Marshal(&v) 247 assert.Nil(t, err, "Error should be nil") 248 assert.Equal( 249 t, 250 `{"interfaceVal":1}`, 251 string(r), 252 "Result of marshalling is different as the one expected") 253 }) 254 t.Run("marshal-interface-float64", func(t *testing.T) { 255 v := testEncodingObjInterfaces{float64(1.1)} 256 r, err := Marshal(&v) 257 assert.Nil(t, err, "Error should be nil") 258 assert.Equal( 259 t, 260 `{"interfaceVal":1.1}`, 261 string(r), 262 "Result of marshalling is different as the one expected") 263 }) 264 t.Run("marshal-interface-float32", func(t *testing.T) { 265 v := testEncodingObjInterfaces{float32(1.1)} 266 r, err := Marshal(&v) 267 assert.Nil(t, err, "Error should be nil") 268 assert.Equal( 269 t, 270 `{"interfaceVal":1.1}`, 271 string(r), 272 "Result of marshalling is different as the one expected") 273 }) 274 t.Run("marshal-object-func", func(t *testing.T) { 275 f := EncodeObjectFunc(func(enc *Encoder) { 276 enc.AddStringKeyOmitEmpty("test", "test") 277 }) 278 r, err := Marshal(f) 279 assert.Nil(t, err, "Error should be nil") 280 assert.Equal( 281 t, 282 `{"test":"test"}`, 283 string(r), 284 "Result of marshalling is different as the one expected") 285 }) 286 t.Run("marshal-any-object", func(t *testing.T) { 287 test := struct { 288 Foo string 289 Bar int 290 }{ 291 "test", 292 100, 293 } 294 r, err := MarshalAny(test) 295 assert.Nil(t, err, "Error should be nil") 296 assert.Equal( 297 t, 298 `{"Foo":"test","Bar":100}`, 299 string(r), 300 "Result of marshalling is different as the one expected") 301 }) 302 } 303 304 type TestObectOmitEmpty struct { 305 nonNiler int 306 testInt int 307 testFloat float64 308 testFloat32 float32 309 testString string 310 testBool bool 311 testObectOmitEmpty *TestObectOmitEmpty 312 testObect *TestObectOmitEmpty 313 } 314 315 func (t *TestObectOmitEmpty) IsNil() bool { 316 return t == nil 317 } 318 319 func (t *TestObectOmitEmpty) MarshalJSONObject(enc *Encoder) { 320 enc.AddIntKeyOmitEmpty("testInt", t.testInt) 321 enc.AddIntKeyOmitEmpty("testIntNotEmpty", 1) 322 enc.AddFloatKeyOmitEmpty("testFloat", t.testFloat) 323 enc.AddFloatKeyOmitEmpty("testFloatNotEmpty", 1.1) 324 enc.AddFloat32KeyOmitEmpty("testFloat32", t.testFloat32) 325 enc.AddFloat32KeyOmitEmpty("testFloat32NotEmpty", 1.1) 326 enc.AddStringKeyOmitEmpty("testString", t.testString) 327 enc.AddStringKeyOmitEmpty("testStringNotEmpty", "foo") 328 enc.AddBoolKeyOmitEmpty("testBool", t.testBool) 329 enc.AddBoolKeyOmitEmpty("testBoolNotEmpty", true) 330 enc.AddObjectKeyOmitEmpty("testObect", t.testObect) 331 enc.AddObjectKeyOmitEmpty("testObectOmitEmpty", t.testObectOmitEmpty) 332 enc.AddArrayKeyOmitEmpty("testArrayOmitEmpty", TestEncodingArrStrings{}) 333 enc.AddArrayKeyOmitEmpty("testArray", TestEncodingArrStrings{"foo"}) 334 } 335 336 type TestObectOmitEmptyInterface struct{} 337 338 func (t *TestObectOmitEmptyInterface) IsNil() bool { 339 return t == nil 340 } 341 342 func (t *TestObectOmitEmptyInterface) MarshalJSONObject(enc *Encoder) { 343 enc.AddInterfaceKeyOmitEmpty("testInt", 0) 344 enc.AddInterfaceKeyOmitEmpty("testInt64", int64(0)) 345 enc.AddInterfaceKeyOmitEmpty("testInt32", int32(0)) 346 enc.AddInterfaceKeyOmitEmpty("testInt16", int16(0)) 347 enc.AddInterfaceKeyOmitEmpty("testInt8", int8(0)) 348 enc.AddInterfaceKeyOmitEmpty("testUint8", uint8(0)) 349 enc.AddInterfaceKeyOmitEmpty("testUint16", uint16(0)) 350 enc.AddInterfaceKeyOmitEmpty("testUint32", uint32(0)) 351 enc.AddInterfaceKeyOmitEmpty("testUint64", uint64(0)) 352 enc.AddInterfaceKeyOmitEmpty("testIntNotEmpty", 1) 353 enc.AddInterfaceKeyOmitEmpty("testFloat", 0) 354 enc.AddInterfaceKeyOmitEmpty("testFloatNotEmpty", 1.1) 355 enc.AddInterfaceKeyOmitEmpty("testFloat32", float32(0)) 356 enc.AddInterfaceKeyOmitEmpty("testFloat32NotEmpty", float32(1.1)) 357 enc.AddInterfaceKeyOmitEmpty("testString", "") 358 enc.AddInterfaceKeyOmitEmpty("testStringNotEmpty", "foo") 359 enc.AddInterfaceKeyOmitEmpty("testBool", false) 360 enc.AddInterfaceKeyOmitEmpty("testBoolNotEmpty", true) 361 enc.AddInterfaceKeyOmitEmpty("testObectOmitEmpty", nil) 362 enc.AddInterfaceKeyOmitEmpty("testObect", &TestEncoding{}) 363 enc.AddInterfaceKeyOmitEmpty("testArr", &TestEncodingArrStrings{}) 364 } 365 366 func TestEncoderObjectOmitEmpty(t *testing.T) { 367 t.Run("encoder-omit-empty-all-types", func(t *testing.T) { 368 v := &TestObectOmitEmpty{ 369 nonNiler: 1, 370 testInt: 0, 371 testObect: &TestObectOmitEmpty{testInt: 1}, 372 } 373 r, err := MarshalJSONObject(v) 374 assert.Nil(t, err, "Error should be nil") 375 assert.Equal( 376 t, 377 `{"testIntNotEmpty":1,"testFloatNotEmpty":1.1,"testFloat32NotEmpty":1.1,"testStringNotEmpty":"foo","testBoolNotEmpty":true,"testObect":{"testInt":1,"testIntNotEmpty":1,"testFloatNotEmpty":1.1,"testFloat32NotEmpty":1.1,"testStringNotEmpty":"foo","testBoolNotEmpty":true,"testArray":["foo"]},"testArray":["foo"]}`, 378 string(r), 379 "Result of marshalling is different as the one expected", 380 ) 381 }) 382 383 t.Run("encoder-omit-empty-interface", func(t *testing.T) { 384 v := &TestObectOmitEmptyInterface{} 385 r, err := MarshalJSONObject(v) 386 assert.Nil(t, err, "Error should be nil") 387 assert.Equal( 388 t, 389 `{"testIntNotEmpty":1,"testFloatNotEmpty":1.1,"testFloat32NotEmpty":1.1,"testStringNotEmpty":"foo","testBoolNotEmpty":true,"testObect":{"test":"","test2":"","testInt":0,"testBool":false,"testArr":[],"testF64":0,"testF32":0,"sub":{}}}`, 390 string(r), 391 "Result of marshalling is different as the one expected", 392 ) 393 }) 394 } 395 396 func TestEncoderObjectEncodeAPIError(t *testing.T) { 397 t.Run("interface-key-error", func(t *testing.T) { 398 builder := &strings.Builder{} 399 enc := NewEncoder(builder) 400 err := enc.EncodeObject(&testObjectWithUnknownType{struct{}{}}) 401 assert.NotNil(t, err, "Error should not be nil") 402 assert.Equal(t, "Invalid type struct {} provided to Marshal", err.Error(), "err.Error() should be 'Invalid type struct {} provided to Marshal'") 403 }) 404 t.Run("write-error", func(t *testing.T) { 405 w := TestWriterError("") 406 enc := NewEncoder(w) 407 err := enc.EncodeObject(&testObject{}) 408 assert.NotNil(t, err, "Error should not be nil") 409 assert.Equal(t, "Test Error", err.Error(), "err.Error() should be 'Test Error'") 410 }) 411 t.Run("interface-error", func(t *testing.T) { 412 builder := &strings.Builder{} 413 enc := NewEncoder(builder) 414 enc.AddInterfaceKeyOmitEmpty("test", struct{}{}) 415 assert.NotNil(t, enc.err, "enc.Err() should not be nil") 416 }) 417 t.Run("pool-error", func(t *testing.T) { 418 v := &TestEncoding{} 419 enc := BorrowEncoder(nil) 420 enc.isPooled = 1 421 defer func() { 422 err := recover() 423 assert.NotNil(t, err, "err shouldnt be nil") 424 assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError") 425 assert.Equal(t, "Invalid usage of pooled encoder", err.(InvalidUsagePooledEncoderError).Error(), "err should be of type InvalidUsagePooledDecoderError") 426 }() 427 _ = enc.EncodeObject(v) 428 assert.True(t, false, "should not be called as it should have panicked") 429 }) 430 } 431 432 func TestEncoderObjectKeyNullEmpty(t *testing.T) { 433 var testCases = []struct { 434 name string 435 baseJSON string 436 expectedJSON string 437 }{ 438 { 439 name: "basic 1st elem", 440 baseJSON: "{", 441 expectedJSON: `{"foo":null,"bar":{"test":"","test2":"","testInt":0,"testBool":false,"testArr":[],"testF64":0,"testF32":0,"sub":{}}`, 442 }, 443 { 444 name: "basic 2nd elem", 445 baseJSON: `{"test":"test"`, 446 expectedJSON: `{"test":"test","foo":null,"bar":{"test":"","test2":"","testInt":0,"testBool":false,"testArr":[],"testF64":0,"testF32":0,"sub":{}}`, 447 }, 448 } 449 for _, testCase := range testCases { 450 t.Run(testCase.name, func(t *testing.T) { 451 var b strings.Builder 452 var enc = NewEncoder(&b) 453 enc.writeString(testCase.baseJSON) 454 enc.AddObjectKeyNullEmpty("foo", (*TestEncoding)(nil)) 455 enc.ObjectKeyNullEmpty("bar", &TestEncoding{}) 456 enc.Write() 457 assert.Equal(t, testCase.expectedJSON, b.String()) 458 }) 459 } 460 } 461 462 func TestEncoderObjectNullEmpty(t *testing.T) { 463 var testCases = []struct { 464 name string 465 baseJSON string 466 expectedJSON string 467 }{ 468 { 469 name: "basic 1st elem", 470 baseJSON: "[", 471 expectedJSON: `[null,{"test":"","test2":"","testInt":0,"testBool":false,"testArr":[],"testF64":0,"testF32":0,"sub":{}}`, 472 }, 473 { 474 name: "basic 2nd elem", 475 baseJSON: `["test"`, 476 expectedJSON: `["test",null,{"test":"","test2":"","testInt":0,"testBool":false,"testArr":[],"testF64":0,"testF32":0,"sub":{}}`, 477 }, 478 } 479 for _, testCase := range testCases { 480 t.Run(testCase.name, func(t *testing.T) { 481 var b strings.Builder 482 var enc = NewEncoder(&b) 483 enc.writeString(testCase.baseJSON) 484 enc.AddObjectNullEmpty((*TestEncoding)(nil)) 485 enc.ObjectNullEmpty(&TestEncoding{}) 486 enc.Write() 487 assert.Equal(t, testCase.expectedJSON, b.String()) 488 }) 489 } 490 } 491 492 type ObjectWithKeys struct { 493 Str string 494 Int int 495 Int64 int64 496 Int32 int32 497 Int16 int16 498 Int8 int8 499 Uint64 uint64 500 Uint32 uint32 501 Uint16 uint16 502 Uint8 uint8 503 Float64 float64 504 Float32 float32 505 Bool bool 506 Obj *ObjectWithKeys 507 Slice TestEncodingArrStrings 508 Time *time.Time 509 EmbeddedJSON *EmbeddedJSON 510 } 511 512 func (o *ObjectWithKeys) MarshalJSONObject(enc *Encoder) { 513 enc.StringKey("string", o.Str) 514 enc.StringKeyOmitEmpty("string", o.Str) 515 enc.StringKeyNullEmpty("string", o.Str) 516 enc.IntKey("int", o.Int) 517 enc.IntKeyOmitEmpty("int", o.Int) 518 enc.IntKeyNullEmpty("int", o.Int) 519 enc.Int64Key("int64", o.Int64) 520 enc.Int64KeyOmitEmpty("int64", o.Int64) 521 enc.Int64KeyNullEmpty("int64", o.Int64) 522 enc.Int32Key("int32", o.Int32) 523 enc.Int32KeyOmitEmpty("int32", o.Int32) 524 enc.Int32KeyNullEmpty("int32", o.Int32) 525 enc.Int16Key("int16", o.Int16) 526 enc.Int16KeyOmitEmpty("int16", o.Int16) 527 enc.Int16KeyNullEmpty("int16", o.Int16) 528 enc.Int8Key("int8", o.Int8) 529 enc.Int8KeyOmitEmpty("int8", o.Int8) 530 enc.Int8KeyNullEmpty("int8", o.Int8) 531 enc.Uint64KeyOmitEmpty("uint64", o.Uint64) 532 enc.Uint64KeyNullEmpty("uint64", o.Uint64) 533 enc.Uint64Key("uint64", o.Uint64) 534 enc.Uint32Key("uint32", o.Uint32) 535 enc.Uint32KeyOmitEmpty("uint32", o.Uint32) 536 enc.Uint32KeyNullEmpty("uint32", o.Uint32) 537 enc.Uint16KeyOmitEmpty("uint16", o.Uint16) 538 enc.Uint16KeyNullEmpty("uint16", o.Uint16) 539 enc.Uint16Key("uint16", o.Uint16) 540 enc.Uint8Key("uint8", o.Uint8) 541 enc.Uint8KeyOmitEmpty("uint8", o.Uint8) 542 enc.Uint8KeyNullEmpty("uint8", o.Uint8) 543 enc.Float64Key("float64", o.Float64) 544 enc.Float64KeyOmitEmpty("float64", o.Float64) 545 enc.Float64KeyNullEmpty("float64", o.Float64) 546 enc.Float32Key("float32", o.Float32) 547 enc.Float32KeyOmitEmpty("float32", o.Float32) 548 enc.Float32KeyNullEmpty("float32", o.Float32) 549 enc.BoolKey("bool", o.Bool) 550 enc.BoolKeyOmitEmpty("bool", o.Bool) 551 enc.BoolKeyNullEmpty("bool", o.Bool) 552 enc.ObjectKeyOmitEmpty("object", o.Obj) 553 enc.ObjectKeyNullEmpty("object", o.Obj) 554 enc.ObjectKey("object", o.Obj) 555 enc.ArrayKey("array", o.Slice) 556 enc.ArrayKeyOmitEmpty("array", o.Slice) 557 enc.ArrayKeyNullEmpty("array", o.Slice) 558 enc.TimeKey("time", o.Time, time.RFC3339) 559 enc.AddEmbeddedJSONKey("ejson", o.EmbeddedJSON) 560 enc.AddEmbeddedJSONKeyOmitEmpty("ejson", o.EmbeddedJSON) 561 enc.NullKey("null") 562 } 563 564 func (o *ObjectWithKeys) IsNil() bool { 565 return o == nil 566 } 567 568 type NilObject struct{} 569 570 func (n *NilObject) MarshalJSONObject(enc *Encoder) {} 571 func (n *NilObject) IsNil() bool { return true } 572 573 func TestEncodeObjectWithKeys(t *testing.T) { 574 t.Run( 575 "should not encode any key", 576 func(t *testing.T) { 577 var b strings.Builder 578 var enc = NewEncoder(&b) 579 var o = &ObjectWithKeys{} 580 var err = enc.EncodeObjectKeys(o, []string{}) 581 assert.Nil(t, err) 582 assert.Equal(t, `{}`, b.String()) 583 }, 584 ) 585 t.Run( 586 "should encode some keys", 587 func(t *testing.T) { 588 var b strings.Builder 589 var enc = NewEncoder(&b) 590 var o = &ObjectWithKeys{Str: "hello", Int: 420} 591 var err = enc.EncodeObjectKeys(o, []string{"string", "int"}) 592 assert.Nil(t, err) 593 assert.Equal( 594 t, 595 `{"string":"hello","string":"hello","string":"hello","int":420,"int":420,"int":420}`, 596 b.String(), 597 ) 598 }, 599 ) 600 t.Run("write-error", func(t *testing.T) { 601 w := TestWriterError("") 602 enc := NewEncoder(w) 603 o := &ObjectWithKeys{Str: "hello", Int: 420} 604 err := enc.EncodeObjectKeys(o, []string{"string", "int"}) 605 assert.NotNil(t, err, "Error should not be nil") 606 assert.Equal(t, "Test Error", err.Error(), "err.Error() should be 'Test Error'") 607 }) 608 t.Run("pool-error", func(t *testing.T) { 609 v := &TestEncoding{} 610 enc := BorrowEncoder(nil) 611 enc.isPooled = 1 612 defer func() { 613 err := recover() 614 assert.NotNil(t, err, "err shouldnt be nil") 615 assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError") 616 assert.Equal(t, "Invalid usage of pooled encoder", err.(InvalidUsagePooledEncoderError).Error(), "err should be of type InvalidUsagePooledDecoderError") 617 }() 618 _ = enc.EncodeObjectKeys(v, []string{}) 619 assert.True(t, false, "should not be called as it should have panicked") 620 }) 621 t.Run("interface-key-error", func(t *testing.T) { 622 builder := &strings.Builder{} 623 enc := NewEncoder(builder) 624 err := enc.EncodeObjectKeys(&testObjectWithUnknownType{struct{}{}}, []string{}) 625 assert.NotNil(t, err, "Error should not be nil") 626 assert.Equal(t, "Invalid type struct {} provided to Marshal", err.Error(), "err.Error() should be 'Invalid type struct {} provided to Marshal'") 627 }) 628 t.Run("encode-object-with-keys", func(t *testing.T) { 629 b := &strings.Builder{} 630 enc := NewEncoder(b) 631 err := enc.EncodeObjectKeys(EncodeObjectFunc(func(enc *Encoder) { 632 enc.ObjectKeyWithKeys("test", EncodeObjectFunc(func(enc *Encoder) { 633 enc.StringKey("test", "hello") 634 enc.StringKey("test2", "hello") 635 }), []string{"test"}) 636 }), []string{}) 637 assert.Nil(t, err, "Error should not be nil") 638 assert.Equal(t, `{}`, b.String()) 639 }) 640 t.Run("encode-object-with-keys", func(t *testing.T) { 641 b := &strings.Builder{} 642 enc := NewEncoder(b) 643 err := enc.EncodeObject(EncodeObjectFunc(func(enc *Encoder) { 644 enc.ObjectKeyWithKeys("test", EncodeObjectFunc(func(enc *Encoder) { 645 enc.keys = nil 646 enc.StringKey("test", "hello") 647 enc.StringKey("test2", "hello") 648 }), []string{"test"}) 649 })) 650 assert.Nil(t, err, "Error should not be nil") 651 assert.Equal(t, `{"test":{}}`, b.String()) 652 }) 653 t.Run("encode-object-with-keys", func(t *testing.T) { 654 b := &strings.Builder{} 655 enc := NewEncoder(b) 656 err := enc.EncodeObject(EncodeObjectFunc(func(enc *Encoder) { 657 enc.ObjectKeyWithKeys("test", EncodeObjectFunc(func(enc *Encoder) { 658 enc.StringKey("test", "hello") 659 enc.StringKey("test2", "hello") 660 }), []string{"test"}) 661 })) 662 assert.Nil(t, err, "Error should not be nil") 663 assert.Equal(t, `{"test":{"test":"hello"}}`, b.String()) 664 }) 665 t.Run("encode-object-with-keys", func(t *testing.T) { 666 b := &strings.Builder{} 667 enc := NewEncoder(b) 668 err := enc.EncodeObject(EncodeObjectFunc(func(enc *Encoder) { 669 enc.writeByte(' ') 670 enc.ObjectKeyWithKeys("test", EncodeObjectFunc(func(enc *Encoder) { 671 enc.StringKey("test", "hello") 672 enc.StringKey("test2", "hello") 673 }), []string{"test"}) 674 })) 675 assert.Nil(t, err, "Error should not be nil") 676 assert.Equal(t, `{ ,"test":{"test":"hello"}}`, b.String()) 677 }) 678 t.Run("encode-object-with-keys", func(t *testing.T) { 679 b := &strings.Builder{} 680 enc := NewEncoder(b) 681 err := enc.EncodeObject(EncodeObjectFunc(func(enc *Encoder) { 682 enc.writeByte(' ') 683 enc.ObjectKeyWithKeys("test", &NilObject{}, []string{}) 684 })) 685 assert.Nil(t, err, "Error should not be nil") 686 assert.Equal(t, `{ ,"test":{}}`, b.String()) 687 }) 688 t.Run("encode-object-with-keys", func(t *testing.T) { 689 b := &strings.Builder{} 690 enc := NewEncoder(b) 691 err := enc.EncodeArray(EncodeArrayFunc(func(enc *Encoder) { 692 enc.ObjectWithKeys(EncodeObjectFunc(func(enc *Encoder) { 693 enc.StringKey("test", "hello") 694 enc.StringKey("test2", "hello") 695 }), []string{"test"}) 696 })) 697 assert.Nil(t, err, "Error should not be nil") 698 assert.Equal(t, `[{"test":"hello"}]`, b.String()) 699 }) 700 t.Run("encode-object-with-keys", func(t *testing.T) { 701 b := &strings.Builder{} 702 enc := NewEncoder(b) 703 err := enc.EncodeArray(EncodeArrayFunc(func(enc *Encoder) { 704 enc.writeByte(' ') 705 enc.ObjectWithKeys(EncodeObjectFunc(func(enc *Encoder) { 706 enc.StringKey("test", "hello") 707 enc.StringKey("test2", "hello") 708 }), []string{"test"}) 709 })) 710 assert.Nil(t, err, "Error should not be nil") 711 assert.Equal(t, `[ ,{"test":"hello"}]`, b.String()) 712 }) 713 t.Run("encode-object-with-keys", func(t *testing.T) { 714 b := &strings.Builder{} 715 enc := NewEncoder(b) 716 err := enc.EncodeArray(EncodeArrayFunc(func(enc *Encoder) { 717 enc.ObjectWithKeys(&NilObject{}, []string{}) 718 })) 719 assert.Nil(t, err, "Error should not be nil") 720 assert.Equal(t, `[{}]`, b.String()) 721 }) 722 t.Run("encode-object-with-keys", func(t *testing.T) { 723 b := &strings.Builder{} 724 enc := NewEncoder(b) 725 err := enc.EncodeArray(EncodeArrayFunc(func(enc *Encoder) { 726 enc.writeByte(' ') 727 enc.ObjectWithKeys(&NilObject{}, []string{}) 728 })) 729 assert.Nil(t, err, "Error should not be nil") 730 assert.Equal(t, `[ ,{}]`, b.String()) 731 }) 732 }