diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterAnyExtensions.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterAnyExtensions.cs index fd2ff1387..f7559f0f7 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiWriterAnyExtensions.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterAnyExtensions.cs @@ -68,13 +68,13 @@ public static void WriteAny(this IOpenApiWriter writer, JsonNode node) writer.WriteObject(node as JsonObject); break; case JsonValueKind.String: // Primitive - writer.WritePrimitive(node); + writer.WritePrimitive(node.AsValue()); break; case JsonValueKind.Number: // Primitive - writer.WritePrimitive(node); + writer.WritePrimitive(node.AsValue()); break; case JsonValueKind.True or JsonValueKind.False: // Primitive - writer.WritePrimitive(node); + writer.WritePrimitive(node.AsValue()); break; case JsonValueKind.Null: // null writer.WriteNull(); @@ -109,72 +109,33 @@ private static void WriteObject(this IOpenApiWriter writer, JsonObject entity) writer.WriteEndObject(); } - private static void WritePrimitive(this IOpenApiWriter writer, JsonNode primitive) + private static void WritePrimitive(this IOpenApiWriter writer, JsonValue jsonValue) { - Utils.CheckArgumentNull(writer); - - var valueKind = primitive.GetValueKind(); - - if (valueKind == JsonValueKind.String && primitive is JsonValue jsonStrValue) - { - if (jsonStrValue.TryGetValue(out var dto)) - { - writer.WriteValue(dto); - } - else if (jsonStrValue.TryGetValue(out var dt)) - { - writer.WriteValue(dt); - } - else if (jsonStrValue.TryGetValue(out var strValue)) - { - // check whether string is actual string or date time object - if (DateTimeOffset.TryParse(strValue, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var dateTimeOffset)) - { - writer.WriteValue(dateTimeOffset); - } - else if (DateTime.TryParse(strValue, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var dateTime)) - { // order matters, DTO needs to be checked first!!! - writer.WriteValue(dateTime); - } - else - { - writer.WriteValue(strValue); - } - } - } - - else if (valueKind == JsonValueKind.Number && primitive is JsonValue jsonValue) - { - - if (jsonValue.TryGetValue(out var decimalValue)) - { - writer.WriteValue(decimalValue); - } - else if (jsonValue.TryGetValue(out var doubleValue)) - { - writer.WriteValue(doubleValue); - } - else if (jsonValue.TryGetValue(out var floatValue)) - { - writer.WriteValue(floatValue); - } - else if (jsonValue.TryGetValue(out var longValue)) - { - writer.WriteValue(longValue); - } - else if (jsonValue.TryGetValue(out var intValue)) - { - writer.WriteValue(intValue); - } - } - else if (valueKind is JsonValueKind.False) - { - writer.WriteValue(false); - } - else if (valueKind is JsonValueKind.True) - { - writer.WriteValue(true); - } + if (jsonValue.TryGetValue(out string stringValue)) + writer.WriteValue(stringValue); + else if (jsonValue.TryGetValue(out DateTime dateTimeValue)) + writer.WriteValue(dateTimeValue.ToString("o", CultureInfo.InvariantCulture)); // ISO 8601 format + else if (jsonValue.TryGetValue(out DateTimeOffset dateTimeOffsetValue)) + writer.WriteValue(dateTimeOffsetValue.ToString("o", CultureInfo.InvariantCulture)); +#if NET6_0_OR_GREATER + else if (jsonValue.TryGetValue(out DateOnly dateOnlyValue)) + writer.WriteValue(dateOnlyValue.ToString("o", CultureInfo.InvariantCulture)); + else if (jsonValue.TryGetValue(out TimeOnly timeOnlyValue)) + writer.WriteValue(timeOnlyValue.ToString("o", CultureInfo.InvariantCulture)); +#endif + else if (jsonValue.TryGetValue(out bool boolValue)) + writer.WriteValue(boolValue); + // write number values + else if (jsonValue.TryGetValue(out decimal decimalValue)) + writer.WriteValue(decimalValue); + else if (jsonValue.TryGetValue(out double doubleValue)) + writer.WriteValue(doubleValue); + else if (jsonValue.TryGetValue(out float floatValue)) + writer.WriteValue(floatValue); + else if (jsonValue.TryGetValue(out long longValue)) + writer.WriteValue(longValue); + else if (jsonValue.TryGetValue(out int intValue)) + writer.WriteValue(intValue); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs index f7c30f65e..1c7475ea3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs @@ -542,6 +542,43 @@ public void ParseSchemaWithUnrecognizedKeywordsWorks() Assert.Equal(2, schema.UnrecognizedKeywords.Count); } + [Fact] + public void ParseSchemaExampleWithPrimitivesWorks() + { + var expected1 = @"{ + ""type"": ""string"", + ""example"": ""2024-01-02"" +}"; + + var expected2 = @"{ + ""type"": ""string"", + ""example"": ""3.14"" +}"; + var schema = new OpenApiSchema() + { + Type = JsonSchemaType.String, + Example = JsonValue.Create("2024-01-02") + }; + + var schema2 = new OpenApiSchema() + { + Type = JsonSchemaType.String, + Example = JsonValue.Create("3.14") + }; + + var textWriter = new StringWriter(); + var writer = new OpenApiJsonWriter(textWriter); + schema.SerializeAsV31(writer); + var actual1 = textWriter.ToString(); + Assert.Equal(expected1.MakeLineBreaksEnvironmentNeutral(), actual1.MakeLineBreaksEnvironmentNeutral()); + + textWriter = new StringWriter(); + writer = new OpenApiJsonWriter(textWriter); + schema2.SerializeAsV31(writer); + var actual2 = textWriter.ToString(); + Assert.Equal(expected2.MakeLineBreaksEnvironmentNeutral(), actual2.MakeLineBreaksEnvironmentNeutral()); + } + [Theory] [InlineData(JsonSchemaType.Integer | JsonSchemaType.String, new[] { "integer", "string" })] [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, new[] { "integer", "null" })] diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs index 2e05a70a3..372d551d5 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs @@ -166,9 +166,8 @@ public async Task WriteOpenApiDateTimeAsJsonWorksAsync(string inputString, bool { // Arrange var input = DateTimeOffset.Parse(inputString, CultureInfo.InvariantCulture); - var dateTimeValue = input; - var json = await WriteAsJsonAsync(dateTimeValue, produceTerseOutput); + var json = await WriteAsJsonAsync(input, produceTerseOutput); var expectedJson = "\"" + input.ToString("o") + "\""; // Assert