Skip to content

Commit 9d9fb6a

Browse files
committed
Add logic for upcasting and downcasting type arrays
1 parent 4fdd0e8 commit 9d9fb6a

File tree

1 file changed

+79
-10
lines changed

1 file changed

+79
-10
lines changed

src/Microsoft.OpenApi/Models/OpenApiSchema.cs

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -483,14 +483,7 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
483483
writer.WriteOptionalCollection(OpenApiConstants.Enum, Enum, (nodeWriter, s) => nodeWriter.WriteAny(s));
484484

485485
// 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);
494487

495488
// allOf
496489
writer.WriteOptionalCollection(OpenApiConstants.AllOf, AllOf, (w, s) => s.SerializeAsV3(w));
@@ -533,7 +526,10 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
533526
writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d));
534527

535528
// nullable
536-
writer.WriteProperty(OpenApiConstants.Nullable, Nullable, false);
529+
if (version is OpenApiSpecVersion.OpenApi3_0)
530+
{
531+
writer.WriteProperty(OpenApiConstants.Nullable, Nullable, false);
532+
}
537533

538534
// discriminator
539535
writer.WriteOptionalObject(OpenApiConstants.Discriminator, Discriminator, (w, s) => s.SerializeAsV3(w));
@@ -557,6 +553,10 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
557553
writer.WriteProperty(OpenApiConstants.Deprecated, Deprecated, false);
558554

559555
// extensions
556+
if (Extensions.ContainsKey(OpenApiConstants.NullableExtension))
557+
{
558+
Extensions.Remove(OpenApiConstants.NullableExtension);
559+
}
560560
writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0);
561561

562562
writer.WriteEndObject();
@@ -670,7 +670,14 @@ internal void SerializeAsV2(
670670
writer.WriteStartObject();
671671

672672
// 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+
}
674681

675682
// description
676683
writer.WriteProperty(OpenApiConstants.Description, Description);
@@ -799,6 +806,35 @@ internal void SerializeAsV2(
799806
writer.WriteEndObject();
800807
}
801808

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+
802838
private object DeepCloneType(object type)
803839
{
804840
if (type == null)
@@ -822,5 +858,38 @@ private object DeepCloneType(object type)
822858

823859
return null;
824860
}
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+
}
825894
}
826895
}

0 commit comments

Comments
 (0)