@@ -483,14 +483,7 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
483
483
writer . WriteOptionalCollection ( OpenApiConstants . Enum , Enum , ( nodeWriter , s ) => nodeWriter . WriteAny ( s ) ) ;
484
484
485
485
// type
486
- if ( Type ? . GetType ( ) == typeof ( string ) )
487
- {
488
- writer . WriteProperty ( OpenApiConstants . Type , ( string ) Type ) ;
489
- }
490
- else
491
- {
492
- writer . WriteOptionalCollection ( OpenApiConstants . Type , ( string [ ] ) Type , ( w , s ) => w . WriteRaw ( s ) ) ;
493
- }
486
+ SerializeTypeProperty ( Type , writer , version ) ;
494
487
495
488
// allOf
496
489
writer . WriteOptionalCollection ( OpenApiConstants . AllOf , AllOf , ( w , s ) => s . SerializeAsV3 ( w ) ) ;
@@ -533,7 +526,10 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
533
526
writer . WriteOptionalObject ( OpenApiConstants . Default , Default , ( w , d ) => w . WriteAny ( d ) ) ;
534
527
535
528
// nullable
536
- writer . WriteProperty ( OpenApiConstants . Nullable , Nullable , false ) ;
529
+ if ( version is OpenApiSpecVersion . OpenApi3_0 )
530
+ {
531
+ writer . WriteProperty ( OpenApiConstants . Nullable , Nullable , false ) ;
532
+ }
537
533
538
534
// discriminator
539
535
writer . WriteOptionalObject ( OpenApiConstants . Discriminator , Discriminator , ( w , s ) => s . SerializeAsV3 ( w ) ) ;
@@ -557,6 +553,10 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
557
553
writer . WriteProperty ( OpenApiConstants . Deprecated , Deprecated , false ) ;
558
554
559
555
// extensions
556
+ if ( Extensions . ContainsKey ( OpenApiConstants . NullableExtension ) )
557
+ {
558
+ Extensions . Remove ( OpenApiConstants . NullableExtension ) ;
559
+ }
560
560
writer . WriteExtensions ( Extensions , OpenApiSpecVersion . OpenApi3_0 ) ;
561
561
562
562
writer . WriteEndObject ( ) ;
@@ -670,7 +670,14 @@ internal void SerializeAsV2(
670
670
writer . WriteStartObject ( ) ;
671
671
672
672
// type
673
- writer . WriteProperty ( OpenApiConstants . Type , ( string ) Type ) ;
673
+ if ( Type is string [ ] array )
674
+ {
675
+ DowncastTypeArrayToV2OrV3 ( array , writer , OpenApiSpecVersion . OpenApi2_0 ) ;
676
+ }
677
+ else
678
+ {
679
+ writer . WriteProperty ( OpenApiConstants . Type , ( string ) Type ) ;
680
+ }
674
681
675
682
// description
676
683
writer . WriteProperty ( OpenApiConstants . Description , Description ) ;
@@ -799,6 +806,35 @@ internal void SerializeAsV2(
799
806
writer . WriteEndObject ( ) ;
800
807
}
801
808
809
+ private void SerializeTypeProperty ( object type , IOpenApiWriter writer , OpenApiSpecVersion version )
810
+ {
811
+ if ( type ? . GetType ( ) == typeof ( string ) )
812
+ {
813
+ // check whether nullable is true for upcasting purposes
814
+ if ( Nullable || Extensions . ContainsKey ( OpenApiConstants . NullableExtension ) )
815
+ {
816
+ // create a new array and insert the type and "null" as values
817
+ Type = new [ ] { ( string ) Type , OpenApiConstants . Null } ;
818
+ }
819
+ else
820
+ {
821
+ writer . WriteProperty ( OpenApiConstants . Type , ( string ) Type ) ;
822
+ }
823
+ }
824
+ if ( Type is string [ ] array )
825
+ {
826
+ // type
827
+ if ( version is OpenApiSpecVersion . OpenApi3_0 )
828
+ {
829
+ DowncastTypeArrayToV2OrV3 ( array , writer , OpenApiSpecVersion . OpenApi3_0 ) ;
830
+ }
831
+ else
832
+ {
833
+ writer . WriteOptionalCollection ( OpenApiConstants . Type , ( string [ ] ) Type , ( w , s ) => w . WriteRaw ( s ) ) ;
834
+ }
835
+ }
836
+ }
837
+
802
838
private object DeepCloneType ( object type )
803
839
{
804
840
if ( type == null )
@@ -822,5 +858,38 @@ private object DeepCloneType(object type)
822
858
823
859
return null ;
824
860
}
861
+
862
+ private void DowncastTypeArrayToV2OrV3 ( string [ ] array , IOpenApiWriter writer , OpenApiSpecVersion version )
863
+ {
864
+ /* If the array has one non-null value, emit Type as string
865
+ * If the array has one null value, emit x-nullable as true
866
+ * If the array has two values, one null and one non-null, emit Type as string and x-nullable as true
867
+ * If the array has more than two values or two non-null values, do not emit type
868
+ * */
869
+
870
+ var nullableProp = version . Equals ( OpenApiSpecVersion . OpenApi2_0 )
871
+ ? OpenApiConstants . NullableExtension
872
+ : OpenApiConstants . Nullable ;
873
+
874
+ if ( array . Length is 1 )
875
+ {
876
+ var value = array [ 0 ] ;
877
+ if ( value is OpenApiConstants . Null )
878
+ {
879
+ writer . WriteProperty ( nullableProp , true ) ;
880
+ }
881
+ else
882
+ {
883
+ writer . WriteProperty ( OpenApiConstants . Type , value ) ;
884
+ }
885
+ }
886
+ else if ( array . Length is 2 && array . Contains ( OpenApiConstants . Null ) )
887
+ {
888
+ // Find the non-null value and write it out
889
+ var nonNullValue = array . First ( v => v != OpenApiConstants . Null ) ;
890
+ writer . WriteProperty ( OpenApiConstants . Type , nonNullValue ) ;
891
+ writer . WriteProperty ( nullableProp , true ) ;
892
+ }
893
+ }
825
894
}
826
895
}
0 commit comments