diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 015fb176a..ebaa49897 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -620,7 +620,10 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, callback); // example - writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, e) => w.WriteAny(e)); + writer.WriteOptionalObject( + OpenApiConstants.Example, + version < OpenApiSpecVersion.OpenApi3_1 ? GetCompatibilityExample() : Example, + (w, e) => w.WriteAny(e)); // deprecated writer.WriteProperty(OpenApiConstants.Deprecated, Deprecated, false); @@ -746,7 +749,7 @@ private void WriteV3CompatibilityKeywords(IOpenApiWriter writer, Action nodeWriter.WriteAny(s)); + writer.WriteOptionalCollection(OpenApiConstants.JsonSchemaExamplesExtension, GetCompatibilityExamplesExtension(), (nodeWriter, s) => nodeWriter.WriteAny(s)); } internal void WriteAsItemsProperties(IOpenApiWriter writer) @@ -960,7 +963,7 @@ private void SerializeAsV2( writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, s) => s.SerializeAsV2(w)); // example - writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, e) => w.WriteAny(e)); + writer.WriteOptionalObject(OpenApiConstants.Example, GetCompatibilityExample(), (w, e) => w.WriteAny(e)); // x-nullable extension SerializeNullable(writer, OpenApiSpecVersion.OpenApi2_0); @@ -991,7 +994,7 @@ private void SerializeAsV2( writer.WriteOptionalMap(OpenApiConstants.PatternPropertiesExtension, PatternProperties, (w, s) => s.SerializeAsV2(w)); } - writer.WriteOptionalCollection(OpenApiConstants.JsonSchemaExamplesExtension, Examples, (nodeWriter, s) => nodeWriter.WriteAny(s)); + writer.WriteOptionalCollection(OpenApiConstants.JsonSchemaExamplesExtension, GetCompatibilityExamplesExtension(), (nodeWriter, s) => nodeWriter.WriteAny(s)); // extensions writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi2_0); @@ -1027,6 +1030,26 @@ private bool TrySerializeTypeProperty(IOpenApiWriter writer, OpenApiSpecVersion return false; } + private JsonNode? GetCompatibilityExample() + { + return Example ?? Examples?.FirstOrDefault(); + } + + private IEnumerable? GetCompatibilityExamplesExtension() + { + if (Examples is null || Examples.Count == 0) + { + return null; + } + + if (Example is not null) + { + return Examples; + } + + return Examples.Count > 1 ? Examples.Skip(1) : null; + } + private static bool IsPowerOfTwo(int x) { return x != 0 && (x & (x - 1)) == 0; diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index 5a31f2e51..6cb47b0d7 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -1755,12 +1755,35 @@ public async Task SerializePatternPropertiesAsExtensionInEarlierVersions(OpenApi [Theory] [InlineData(OpenApiSpecVersion.OpenApi2_0)] [InlineData(OpenApiSpecVersion.OpenApi3_0)] - public async Task SerializeExamplesAsExtensionInEarlierVersions(OpenApiSpecVersion version) + public async Task SerializeSingleExampleAsExampleInV2V3WhenExampleUnset(OpenApiSpecVersion version) { var expected = """ { + "example": "example value" + } + """; + var schema = new OpenApiSchema + { + Examples = + [ + JsonValue.Create("example value")! + ] + }; + + var actual = await schema.SerializeAsJsonAsync(version); + + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); + } + + [Theory] + [InlineData(OpenApiSpecVersion.OpenApi2_0)] + [InlineData(OpenApiSpecVersion.OpenApi3_0)] + public async Task SerializeMultipleExamplesInV2V3WhenExampleUnset(OpenApiSpecVersion version) + { + var expected = """ + { + "example": "example value", "x-jsonschema-examples": [ - "example value", 42 ] }