@@ -477,4 +477,127 @@ await VerifyOpenApiDocument(builder, options, document =>
477477 Assert . Equal ( ReferenceType . Link , responseSchema . Reference . Type ) ;
478478 } ) ;
479479 }
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+ }
480602}
603+ #nullable restore
0 commit comments