@@ -1392,3 +1392,180 @@ func TestDuplicatedFieldDisappears(t *testing.T) {
1392
1392
t .Fatalf ("Marshal: got %s want %s" , got , want )
1393
1393
}
1394
1394
}
1395
+
1396
+ func TestAnonymousFields (t * testing.T ) {
1397
+ tests := []struct {
1398
+ label string // Test name
1399
+ makeInput func () interface {} // Function to create input value
1400
+ want string // Expected JSON output
1401
+ }{{
1402
+ // Both S1 and S2 have a field named X. From the perspective of S,
1403
+ // it is ambiguous which one X refers to.
1404
+ // This should not serialize either field.
1405
+ label : "AmbiguousField" ,
1406
+ makeInput : func () interface {} {
1407
+ type (
1408
+ S1 struct { x , X int }
1409
+ S2 struct { x , X int }
1410
+ S struct {
1411
+ S1
1412
+ S2
1413
+ }
1414
+ )
1415
+ return S {S1 {1 , 2 }, S2 {3 , 4 }}
1416
+ },
1417
+ want : `{}` ,
1418
+ }, {
1419
+ label : "DominantField" ,
1420
+ // Both S1 and S2 have a field named X, but since S has an X field as
1421
+ // well, it takes precedence over S1.X and S2.X.
1422
+ makeInput : func () interface {} {
1423
+ type (
1424
+ S1 struct { x , X int }
1425
+ S2 struct { x , X int }
1426
+ S struct {
1427
+ S1
1428
+ S2
1429
+ x , X int
1430
+ }
1431
+ )
1432
+ return S {S1 {1 , 2 }, S2 {3 , 4 }, 5 , 6 }
1433
+ },
1434
+ want : `{"X":6}` ,
1435
+ }, {
1436
+ // Unexported embedded field of non-struct type should not be serialized.
1437
+ label : "UnexportedEmbeddedInt" ,
1438
+ makeInput : func () interface {} {
1439
+ type (
1440
+ myInt int
1441
+ S struct { myInt }
1442
+ )
1443
+ return S {5 }
1444
+ },
1445
+ want : `{}` ,
1446
+ }, {
1447
+ // Exported embedded field of non-struct type should be serialized.
1448
+ label : "ExportedEmbeddedInt" ,
1449
+ makeInput : func () interface {} {
1450
+ type (
1451
+ MyInt int
1452
+ S struct { MyInt }
1453
+ )
1454
+ return S {5 }
1455
+ },
1456
+ want : `{"MyInt":5}` ,
1457
+ }, {
1458
+ // Unexported embedded field of pointer to non-struct type
1459
+ // should not be serialized.
1460
+ label : "UnexportedEmbeddedIntPointer" ,
1461
+ makeInput : func () interface {} {
1462
+ type (
1463
+ myInt int
1464
+ S struct { * myInt }
1465
+ )
1466
+ s := S {new (myInt )}
1467
+ * s .myInt = 5
1468
+ return s
1469
+ },
1470
+ want : `{}` ,
1471
+ }, {
1472
+ // Exported embedded field of pointer to non-struct type
1473
+ // should be serialized.
1474
+ label : "ExportedEmbeddedIntPointer" ,
1475
+ makeInput : func () interface {} {
1476
+ type (
1477
+ MyInt int
1478
+ S struct { * MyInt }
1479
+ )
1480
+ s := S {new (MyInt )}
1481
+ * s .MyInt = 5
1482
+ return s
1483
+ },
1484
+ want : `{"MyInt":5}` ,
1485
+ }, {
1486
+ // Exported fields of embedded structs should have their
1487
+ // exported fields be serialized regardless of whether the struct types
1488
+ // themselves are exported.
1489
+ label : "EmbeddedStruct" ,
1490
+ makeInput : func () interface {} {
1491
+ type (
1492
+ s1 struct { x , X int }
1493
+ S2 struct { y , Y int }
1494
+ S struct {
1495
+ s1
1496
+ S2
1497
+ }
1498
+ )
1499
+ return S {s1 {1 , 2 }, S2 {3 , 4 }}
1500
+ },
1501
+ want : `{"X":2,"Y":4}` ,
1502
+ }, {
1503
+ // Exported fields of pointers to embedded structs should have their
1504
+ // exported fields be serialized regardless of whether the struct types
1505
+ // themselves are exported.
1506
+ label : "EmbeddedStructPointer" ,
1507
+ makeInput : func () interface {} {
1508
+ type (
1509
+ s1 struct { x , X int }
1510
+ S2 struct { y , Y int }
1511
+ S struct {
1512
+ * s1
1513
+ * S2
1514
+ }
1515
+ )
1516
+ return S {& s1 {1 , 2 }, & S2 {3 , 4 }}
1517
+ },
1518
+ want : `{"X":2,"Y":4}` ,
1519
+ }, {
1520
+ // Exported fields on embedded unexported structs at multiple levels
1521
+ // of nesting should still be serialized.
1522
+ label : "NestedStructAndInts" ,
1523
+ makeInput : func () interface {} {
1524
+ type (
1525
+ MyInt1 int
1526
+ MyInt2 int
1527
+ myInt int
1528
+ s2 struct {
1529
+ MyInt2
1530
+ myInt
1531
+ }
1532
+ s1 struct {
1533
+ MyInt1
1534
+ myInt
1535
+ s2
1536
+ }
1537
+ S struct {
1538
+ s1
1539
+ myInt
1540
+ }
1541
+ )
1542
+ return S {s1 {1 , 2 , s2 {3 , 4 }}, 6 }
1543
+ },
1544
+ want : `{"MyInt1":1,"MyInt2":3}` ,
1545
+ }, {
1546
+ // If an anonymous struct pointer field is nil, we should ignore
1547
+ // the embedded fields behind it. Not properly doing so may
1548
+ // result in the wrong output or reflect panics.
1549
+ label : "EmbeddedFieldBehindNilPointer" ,
1550
+ makeInput : func () interface {} {
1551
+ type (
1552
+ S2 struct { Field string }
1553
+ S struct { * S2 }
1554
+ )
1555
+ return S {}
1556
+ },
1557
+ want : `{}` ,
1558
+ }}
1559
+
1560
+ for i , tt := range tests {
1561
+ t .Run (tt .label , func (t * testing.T ) {
1562
+ b , err := json .Marshal (tt .makeInput ())
1563
+ if err != nil {
1564
+ t .Fatalf ("%d: Marshal() = %v, want nil error" , i , err )
1565
+ }
1566
+ if string (b ) != tt .want {
1567
+ t .Fatalf ("%d: Marshal() = %q, want %q" , i , b , tt .want )
1568
+ }
1569
+ })
1570
+ }
1571
+ }
0 commit comments