4
4
using System ;
5
5
using System . Collections . Generic ;
6
6
using System . Linq ;
7
+ using System . Text . Json ;
7
8
using System . Text . Json . Nodes ;
9
+ using Microsoft . OpenApi . Any ;
8
10
using Microsoft . OpenApi . Extensions ;
9
11
using Microsoft . OpenApi . Helpers ;
10
12
using Microsoft . OpenApi . Interfaces ;
@@ -356,12 +358,6 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version
356
358
// default
357
359
writer . WriteOptionalObject ( OpenApiConstants . Default , Default , ( w , d ) => w . WriteAny ( d ) ) ;
358
360
359
- // nullable
360
- if ( version is OpenApiSpecVersion . OpenApi3_0 )
361
- {
362
- writer . WriteProperty ( OpenApiConstants . Nullable , Nullable , false ) ;
363
- }
364
-
365
361
// discriminator
366
362
writer . WriteOptionalObject ( OpenApiConstants . Discriminator , Discriminator , callback ) ;
367
363
@@ -636,20 +632,39 @@ private void SerializeAsV2(
636
632
637
633
private void SerializeTypeProperty ( JsonSchemaType ? type , IOpenApiWriter writer , OpenApiSpecVersion version )
638
634
{
635
+ // check whether nullable is true for upcasting purposes
636
+ var isNullable = Nullable ||
637
+ ( Type . HasValue && Type . Value . HasFlag ( JsonSchemaType . Null ) ) ||
638
+ Extensions is not null &&
639
+ Extensions . TryGetValue ( OpenApiConstants . NullableExtension , out var nullExtRawValue ) &&
640
+ nullExtRawValue is OpenApiAny { Node : JsonNode jsonNode } &&
641
+ jsonNode . GetValueKind ( ) is JsonValueKind . True ;
639
642
if ( type is null )
640
643
{
641
- return ;
642
- }
643
- if ( ! HasMultipleTypes ( type . Value ) )
644
- {
645
- // check whether nullable is true for upcasting purposes
646
- if ( version is OpenApiSpecVersion . OpenApi3_1 && ( Nullable || Extensions . ContainsKey ( OpenApiConstants . NullableExtension ) ) )
644
+ if ( version is OpenApiSpecVersion . OpenApi3_0 && isNullable )
647
645
{
648
- UpCastSchemaTypeToV31 ( type , writer ) ;
646
+ writer . WriteProperty ( OpenApiConstants . Nullable , true ) ;
649
647
}
650
- else
648
+ }
649
+ else if ( ! HasMultipleTypes ( type . Value ) )
650
+ {
651
+
652
+ switch ( version )
651
653
{
652
- writer . WriteProperty ( OpenApiConstants . Type , type . Value . ToIdentifier ( ) ) ;
654
+ case OpenApiSpecVersion . OpenApi3_1 when isNullable :
655
+ UpCastSchemaTypeToV31 ( type . Value , writer ) ;
656
+ break ;
657
+ case OpenApiSpecVersion . OpenApi3_0 when isNullable && type . Value == JsonSchemaType . Null :
658
+ writer . WriteProperty ( OpenApiConstants . Nullable , true ) ;
659
+ writer . WriteProperty ( OpenApiConstants . Type , JsonSchemaType . Object . ToIdentifier ( ) ) ;
660
+ break ;
661
+ case OpenApiSpecVersion . OpenApi3_0 when isNullable && type . Value != JsonSchemaType . Null :
662
+ writer . WriteProperty ( OpenApiConstants . Nullable , true ) ;
663
+ writer . WriteProperty ( OpenApiConstants . Type , type . Value . ToIdentifier ( ) ) ;
664
+ break ;
665
+ default :
666
+ writer . WriteProperty ( OpenApiConstants . Type , type . Value . ToIdentifier ( ) ) ;
667
+ break ;
653
668
}
654
669
}
655
670
else
@@ -664,6 +679,10 @@ private void SerializeTypeProperty(JsonSchemaType? type, IOpenApiWriter writer,
664
679
var list = ( from JsonSchemaType flag in jsonSchemaTypeValues
665
680
where type . Value . HasFlag ( flag )
666
681
select flag ) . ToList ( ) ;
682
+ if ( Nullable && ! list . Contains ( JsonSchemaType . Null ) )
683
+ {
684
+ list . Add ( JsonSchemaType . Null ) ;
685
+ }
667
686
writer . WriteOptionalCollection ( OpenApiConstants . Type , list , ( w , s ) => w . WriteValue ( s . ToIdentifier ( ) ) ) ;
668
687
}
669
688
}
@@ -681,14 +700,21 @@ private static bool HasMultipleTypes(JsonSchemaType schemaType)
681
700
schemaTypeNumeric != ( int ) JsonSchemaType . Null ;
682
701
}
683
702
684
- private void UpCastSchemaTypeToV31 ( JsonSchemaType ? type , IOpenApiWriter writer )
703
+ private static void UpCastSchemaTypeToV31 ( JsonSchemaType type , IOpenApiWriter writer )
685
704
{
686
705
// create a new array and insert the type and "null" as values
687
- Type = type | JsonSchemaType . Null ;
688
- var list = ( from JsonSchemaType ? flag in jsonSchemaTypeValues // Check if the flag is set in 'type' using a bitwise AND operation
689
- where Type . Value . HasFlag ( flag )
706
+ var temporaryType = type | JsonSchemaType . Null ;
707
+ var list = ( from JsonSchemaType flag in jsonSchemaTypeValues // Check if the flag is set in 'type' using a bitwise AND operation
708
+ where temporaryType . HasFlag ( flag )
690
709
select flag . ToIdentifier ( ) ) . ToList ( ) ;
691
- writer . WriteOptionalCollection ( OpenApiConstants . Type , list , ( w , s ) => w . WriteValue ( s ) ) ;
710
+ if ( list . Count > 1 )
711
+ {
712
+ writer . WriteOptionalCollection ( OpenApiConstants . Type , list , ( w , s ) => w . WriteValue ( s ) ) ;
713
+ }
714
+ else
715
+ {
716
+ writer . WriteProperty ( OpenApiConstants . Type , list [ 0 ] ) ;
717
+ }
692
718
}
693
719
694
720
#if NET5_0_OR_GREATER
@@ -711,7 +737,7 @@ private void DowncastTypeArrayToV2OrV3(JsonSchemaType schemaType, IOpenApiWriter
711
737
712
738
if ( ! HasMultipleTypes ( schemaType ^ JsonSchemaType . Null ) && ( schemaType & JsonSchemaType . Null ) == JsonSchemaType . Null ) // checks for two values and one is null
713
739
{
714
- foreach ( JsonSchemaType ? flag in jsonSchemaTypeValues )
740
+ foreach ( JsonSchemaType flag in jsonSchemaTypeValues )
715
741
{
716
742
// Skip if the flag is not set or if it's the Null flag
717
743
if ( schemaType . HasFlag ( flag ) && flag != JsonSchemaType . Null )
0 commit comments