@@ -133,7 +133,11 @@ public async Task SerializeSchemaReferenceAsV31JsonWorks(bool produceTerseOutput
133133 WriteOnly = false ,
134134 Deprecated = true ,
135135 Default = JsonValue . Create ( "reference default" ) ,
136- Examples = new List < JsonNode > { JsonValue . Create ( "reference example" ) }
136+ Examples = new List < JsonNode > { JsonValue . Create ( "reference example" ) } ,
137+ Extensions = new Dictionary < string , IOpenApiExtension >
138+ {
139+ [ "x-custom" ] = new JsonNodeExtension ( JsonValue . Create ( "custom value" ) )
140+ }
137141 } ;
138142
139143 var outputStringWriter = new StringWriter ( CultureInfo . InvariantCulture ) ;
@@ -150,7 +154,7 @@ public async Task SerializeSchemaReferenceAsV31JsonWorks(bool produceTerseOutput
150154 [ Theory ]
151155 [ InlineData ( true ) ]
152156 [ InlineData ( false ) ]
153- public async Task SerializeSchemaReferenceAsV3JsonWorks ( bool produceTerseOutput )
157+ public async Task SerializeSchemaReferenceAsV32JsonWorks ( bool produceTerseOutput )
154158 {
155159 // Arrange
156160 var reference = new OpenApiSchemaReference ( "Pet" , null )
@@ -161,7 +165,43 @@ public async Task SerializeSchemaReferenceAsV3JsonWorks(bool produceTerseOutput)
161165 WriteOnly = false ,
162166 Deprecated = true ,
163167 Default = JsonValue . Create ( "reference default" ) ,
164- Examples = new List < JsonNode > { JsonValue . Create ( "reference example" ) }
168+ Examples = new List < JsonNode > { JsonValue . Create ( "reference example" ) } ,
169+ Extensions = new Dictionary < string , IOpenApiExtension >
170+ {
171+ [ "x-custom" ] = new JsonNodeExtension ( JsonValue . Create ( "custom value" ) )
172+ }
173+ } ;
174+
175+ var outputStringWriter = new StringWriter ( CultureInfo . InvariantCulture ) ;
176+ var writer = new OpenApiJsonWriter ( outputStringWriter , new OpenApiJsonWriterSettings { Terse = produceTerseOutput } ) ;
177+
178+ // Act
179+ reference . SerializeAsV32 ( writer ) ;
180+ await writer . FlushAsync ( ) ;
181+
182+ // Assert
183+ await Verifier . Verify ( outputStringWriter ) . UseParameters ( produceTerseOutput ) ;
184+ }
185+
186+ [ Theory ]
187+ [ InlineData ( true ) ]
188+ [ InlineData ( false ) ]
189+ public async Task SerializeSchemaReferenceAsV3JsonWorks ( bool produceTerseOutput )
190+ {
191+ // Arrange - Extensions should NOT appear in v3.0 output
192+ var reference = new OpenApiSchemaReference ( "Pet" , null )
193+ {
194+ Title = "Reference Title" ,
195+ Description = "Reference Description" ,
196+ ReadOnly = true ,
197+ WriteOnly = false ,
198+ Deprecated = true ,
199+ Default = JsonValue . Create ( "reference default" ) ,
200+ Examples = new List < JsonNode > { JsonValue . Create ( "reference example" ) } ,
201+ Extensions = new Dictionary < string , IOpenApiExtension >
202+ {
203+ [ "x-custom" ] = new JsonNodeExtension ( JsonValue . Create ( "custom value" ) )
204+ }
165205 } ;
166206
167207 var outputStringWriter = new StringWriter ( CultureInfo . InvariantCulture ) ;
@@ -175,6 +215,38 @@ public async Task SerializeSchemaReferenceAsV3JsonWorks(bool produceTerseOutput)
175215 await Verifier . Verify ( outputStringWriter ) . UseParameters ( produceTerseOutput ) ;
176216 }
177217
218+ [ Theory ]
219+ [ InlineData ( true ) ]
220+ [ InlineData ( false ) ]
221+ public async Task SerializeSchemaReferenceAsV2JsonWorks ( bool produceTerseOutput )
222+ {
223+ // Arrange - Extensions should NOT appear in v2 output
224+ var reference = new OpenApiSchemaReference ( "Pet" , null )
225+ {
226+ Title = "Reference Title" ,
227+ Description = "Reference Description" ,
228+ ReadOnly = true ,
229+ WriteOnly = false ,
230+ Deprecated = true ,
231+ Default = JsonValue . Create ( "reference default" ) ,
232+ Examples = new List < JsonNode > { JsonValue . Create ( "reference example" ) } ,
233+ Extensions = new Dictionary < string , IOpenApiExtension >
234+ {
235+ [ "x-custom" ] = new JsonNodeExtension ( JsonValue . Create ( "custom value" ) )
236+ }
237+ } ;
238+
239+ var outputStringWriter = new StringWriter ( CultureInfo . InvariantCulture ) ;
240+ var writer = new OpenApiJsonWriter ( outputStringWriter , new OpenApiJsonWriterSettings { Terse = produceTerseOutput } ) ;
241+
242+ // Act
243+ reference . SerializeAsV2 ( writer ) ;
244+ await writer . FlushAsync ( ) ;
245+
246+ // Assert
247+ await Verifier . Verify ( outputStringWriter ) . UseParameters ( produceTerseOutput ) ;
248+ }
249+
178250 [ Fact ]
179251 public void ParseSchemaReferenceWithAnnotationsWorks ( )
180252 {
@@ -256,5 +328,120 @@ public void ParseSchemaReferenceWithAnnotationsWorks()
256328 Assert . Equal ( "Original Pet Title" , targetSchema . Title ) ;
257329 Assert . Equal ( "Original Pet Description" , targetSchema . Description ) ;
258330 }
331+
332+ [ Fact ]
333+ public void ParseSchemaReferenceWithExtensionsWorks ( )
334+ {
335+ // Arrange
336+ var jsonContent = @"{
337+ ""openapi"": ""3.1.0"",
338+ ""info"": {
339+ ""title"": ""Test API"",
340+ ""version"": ""1.0.0""
341+ },
342+ ""paths"": {
343+ ""/test"": {
344+ ""get"": {
345+ ""responses"": {
346+ ""200"": {
347+ ""description"": ""OK"",
348+ ""content"": {
349+ ""application/json"": {
350+ ""schema"": {
351+ ""$ref"": ""#/components/schemas/Pet"",
352+ ""description"": ""A pet object"",
353+ ""x-custom-extension"": ""custom value"",
354+ ""x-another-extension"": 42
355+ }
356+ }
357+ }
358+ }
359+ }
360+ }
361+ }
362+ },
363+ ""components"": {
364+ ""schemas"": {
365+ ""Pet"": {
366+ ""type"": ""object"",
367+ ""properties"": {
368+ ""name"": {
369+ ""type"": ""string""
370+ }
371+ }
372+ }
373+ }
374+ }
375+ }" ;
376+
377+ // Act
378+ var readResult = OpenApiDocument . Parse ( jsonContent , "json" ) ;
379+ var document = readResult . Document ;
380+
381+ // Assert
382+ Assert . NotNull ( document ) ;
383+ Assert . Empty ( readResult . Diagnostic . Errors ) ;
384+
385+ var schema = document . Paths [ "/test" ] . Operations [ HttpMethod . Get ]
386+ . Responses [ "200" ] . Content [ "application/json" ] . Schema ;
387+
388+ Assert . IsType < OpenApiSchemaReference > ( schema ) ;
389+ var schemaRef = ( OpenApiSchemaReference ) schema ;
390+
391+ // Test that reference-level extensions are parsed
392+ Assert . NotNull ( schemaRef . Extensions ) ;
393+ Assert . Contains ( "x-custom-extension" , schemaRef . Extensions . Keys ) ;
394+ Assert . Contains ( "x-another-extension" , schemaRef . Extensions . Keys ) ;
395+ }
396+
397+ [ Fact ]
398+ public async Task SchemaReferenceExtensionsNotWrittenInV30 ( )
399+ {
400+ // Arrange
401+ var reference = new OpenApiSchemaReference ( "Pet" , null )
402+ {
403+ Description = "Local description" ,
404+ Extensions = new Dictionary < string , IOpenApiExtension >
405+ {
406+ [ "x-custom" ] = new JsonNodeExtension ( JsonValue . Create ( "custom value" ) )
407+ }
408+ } ;
409+
410+ var outputStringWriter = new StringWriter ( CultureInfo . InvariantCulture ) ;
411+ var writer = new OpenApiJsonWriter ( outputStringWriter , new OpenApiJsonWriterSettings { Terse = true } ) ;
412+
413+ // Act
414+ reference . SerializeAsV3 ( writer ) ;
415+ await writer . FlushAsync ( ) ;
416+ var output = outputStringWriter . ToString ( ) ;
417+
418+ // Assert: In v3.0, ONLY $ref should appear - no description, no extensions
419+ Assert . Equal ( @"{""$ref"":""#/components/schemas/Pet""}" , output ) ;
420+ }
421+
422+ [ Fact ]
423+ public async Task SchemaReferenceExtensionsNotWrittenInV2 ( )
424+ {
425+ // Arrange
426+ var reference = new OpenApiSchemaReference ( "Pet" , null )
427+ {
428+ Description = "Local description" ,
429+ Extensions = new Dictionary < string , IOpenApiExtension >
430+ {
431+ [ "x-custom" ] = new JsonNodeExtension ( JsonValue . Create ( "custom value" ) )
432+ }
433+ } ;
434+
435+ var outputStringWriter = new StringWriter ( CultureInfo . InvariantCulture ) ;
436+ var writer = new OpenApiJsonWriter ( outputStringWriter , new OpenApiJsonWriterSettings { Terse = true } ) ;
437+
438+ // Act
439+ reference . SerializeAsV2 ( writer ) ;
440+ await writer . FlushAsync ( ) ;
441+ var output = outputStringWriter . ToString ( ) ;
442+
443+ // Assert: In v2, ONLY $ref should appear - no description, no extensions
444+ Assert . Equal ( @"{""$ref"":""#/definitions/Pet""}" , output ) ;
445+ }
259446 }
260447}
0 commit comments