Skip to content

v2 - Primitive parsing for strings as DateTimes is too greedy #2137

Closed
@captainsafia

Description

@captainsafia

Both @mikekistler and I have observed this bug while interacting with the new JsonNode-based example APIs in v2. The current logic tries to eagerly parse string JsonNodes as date times and write them as such when emitting the final document:

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);
}
}
}

This can cause some rather unintended behaviors. For example, the current implementation casts example strings that are designated as a DateOnly time to DateTime based types. The current implementation will also errenously capture certain string examples (like a float 3.14) as dates.

The following code:

using System.Text.Json.Nodes;
using System.IO;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Writers;

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);
System.Console.WriteLine(textWriter.ToString());

textWriter = new StringWriter();
writer = new OpenApiJsonWriter(textWriter);
schema2.SerializeAsV31(writer);
System.Console.WriteLine(textWriter.ToString());

Produces:

{
  "type": "string",
  "example": "2024-01-02T00:00:00.0000000+00:00"
}
{
  "type": "string",
  "example": "2025-03-14T00:00:00.0000000+00:00"
}

When I would expect it to produce:

{
  "type": "string",
  "example": "2024-01-02"
}
{
  "type": "string",
  "example": "3.14"
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions