@@ -477,4 +477,127 @@ await VerifyOpenApiDocument(builder, options, document =>
477
477
Assert . Equal ( ReferenceType . Link , responseSchema . Reference . Type ) ;
478
478
} ) ;
479
479
}
480
+
481
+ [ Fact ]
482
+ public async Task SupportsNestedSchemasWithSelfReference ( )
483
+ {
484
+ // Arrange
485
+ var builder = CreateBuilder ( ) ;
486
+
487
+ builder . MapPost ( "/" , ( LocationContainer item ) => { } ) ;
488
+
489
+ await VerifyOpenApiDocument ( builder , document =>
490
+ {
491
+ var operation = document . Paths [ "/" ] . Operations [ OperationType . Post ] ;
492
+ var requestSchema = operation . RequestBody . Content [ "application/json" ] . Schema ;
493
+
494
+ // Assert $ref used for top-level
495
+ Assert . Equal ( "LocationContainer" , requestSchema . Reference . Id ) ;
496
+
497
+ // Assert that $ref is used for nested LocationDto
498
+ var locationContainerSchema = requestSchema . GetEffective ( document ) ;
499
+ Assert . Equal ( "LocationDto" , locationContainerSchema . Properties [ "location" ] . Reference . Id ) ;
500
+
501
+ // Assert that $ref is used for nested AddressDto
502
+ var locationSchema = locationContainerSchema . Properties [ "location" ] . GetEffective ( document ) ;
503
+ Assert . Equal ( "AddressDto" , locationSchema . Properties [ "address" ] . Reference . Id ) ;
504
+
505
+ // Assert that $ref is used for related LocationDto
506
+ var addressSchema = locationSchema . Properties [ "address" ] . GetEffective ( document ) ;
507
+ Assert . Equal ( "LocationDto" , addressSchema . Properties [ "relatedLocation" ] . Reference . Id ) ;
508
+ } ) ;
509
+ }
510
+
511
+ [ Fact ]
512
+ public async Task SupportsListNestedSchemasWithSelfReference ( )
513
+ {
514
+ // Arrange
515
+ var builder = CreateBuilder ( ) ;
516
+
517
+ builder . MapPost ( "/" , ( ParentObject item ) => { } ) ;
518
+
519
+ await VerifyOpenApiDocument ( builder , document =>
520
+ {
521
+ var operation = document . Paths [ "/" ] . Operations [ OperationType . Post ] ;
522
+ var requestSchema = operation . RequestBody . Content [ "application/json" ] . Schema ;
523
+
524
+ // Assert $ref used for top-level
525
+ Assert . Equal ( "ParentObject" , requestSchema . Reference . Id ) ;
526
+
527
+ // Assert that $ref is used for nested Children
528
+ var parentSchema = requestSchema . GetEffective ( document ) ;
529
+ Assert . Equal ( "ChildObject" , parentSchema . Properties [ "children" ] . Items . Reference . Id ) ;
530
+
531
+ // Assert that $ref is used for nested Parent
532
+ var childSchema = parentSchema . Properties [ "children" ] . Items . GetEffective ( document ) ;
533
+ Assert . Equal ( "ParentObject" , childSchema . Properties [ "parent" ] . Reference . Id ) ;
534
+ } ) ;
535
+ }
536
+
537
+ [ Fact ]
538
+ public async Task SupportsMultiplePropertiesWithSameType ( )
539
+ {
540
+ // Arrange
541
+ var builder = CreateBuilder ( ) ;
542
+
543
+ builder . MapPost ( "/" , ( Root item ) => { } ) ;
544
+
545
+ await VerifyOpenApiDocument ( builder , document =>
546
+ {
547
+ var operation = document . Paths [ "/" ] . Operations [ OperationType . Post ] ;
548
+ var requestSchema = operation . RequestBody . Content [ "application/json" ] . Schema ;
549
+
550
+ // Assert $ref used for top-level
551
+ Assert . Equal ( "Root" , requestSchema . Reference . Id ) ;
552
+
553
+ // Assert that $ref is used for nested Item1
554
+ var rootSchema = requestSchema . GetEffective ( document ) ;
555
+ Assert . Equal ( "Item" , rootSchema . Properties [ "item1" ] . Reference . Id ) ;
556
+
557
+ // Assert that $ref is used for nested Item2
558
+ Assert . Equal ( "Item" , rootSchema . Properties [ "item2" ] . Reference . Id ) ;
559
+ } ) ;
560
+ }
561
+
562
+ private class Root
563
+ {
564
+ public Item Item1 { get ; set ; } = null ! ;
565
+ public Item Item2 { get ; set ; } = null ! ;
566
+ }
567
+
568
+ private class Item
569
+ {
570
+ public string [ ] Name { get ; set ; } = null ! ;
571
+ public int value { get ; set ; }
572
+ }
573
+
574
+ private class LocationContainer
575
+ {
576
+
577
+ public LocationDto Location { get ; set ; }
578
+ }
579
+
580
+ private class LocationDto
581
+ {
582
+ public AddressDto Address { get ; set ; }
583
+ }
584
+
585
+ private class AddressDto
586
+ {
587
+ public LocationDto RelatedLocation { get ; set ; }
588
+ }
589
+
590
+ #nullable enable
591
+ private class ParentObject
592
+ {
593
+ public int Id { get ; set ; }
594
+ public List < ChildObject > Children { get ; set ; } = [ ] ;
595
+ }
596
+
597
+ private class ChildObject
598
+ {
599
+ public int Id { get ; set ; }
600
+ public required ParentObject Parent { get ; set ; }
601
+ }
480
602
}
603
+ #nullable restore
0 commit comments