Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 29 additions & 68 deletions src/Microsoft.OpenApi/Writers/OpenApiWriterAnyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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<DateTimeOffset>(out var dto))
{
writer.WriteValue(dto);
}
else if (jsonStrValue.TryGetValue<DateTime>(out var dt))
{
writer.WriteValue(dt);
}
else if (jsonStrValue.TryGetValue<string>(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<decimal>(out var decimalValue))
{
writer.WriteValue(decimalValue);
}
else if (jsonValue.TryGetValue<double>(out var doubleValue))
{
writer.WriteValue(doubleValue);
}
else if (jsonValue.TryGetValue<float>(out var floatValue))
{
writer.WriteValue(floatValue);
}
else if (jsonValue.TryGetValue<long>(out var longValue))
{
writer.WriteValue(longValue);
}
else if (jsonValue.TryGetValue<int>(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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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" })]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down