Skip to content

Commit

Permalink
Merge pull request #768 from EdwardCooke/ec-fix-587
Browse files Browse the repository at this point in the history
Fixed DateTime serialization with JSON using single quotes

+semver:breaking
  • Loading branch information
EdwardCooke committed Jan 15, 2023
2 parents 16bd981 + 4277fca commit 306f714
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 2 deletions.
10 changes: 10 additions & 0 deletions YamlDotNet.Test/Serialization/DateTimeConverterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,16 @@ public void Given_Values_WithFormats_WriteYaml_ShouldReturn_Result_WithFirstForm

serialised.Should().ContainEquivalentOf($"datetime: {formatted}");
}

[Fact]
public void JsonCompatible_EncaseDateTimesInDoubleQuotes()
{
var serializer = new SerializerBuilder().JsonCompatible().Build();
var testObject = new TestObject { DateTime = new DateTime(2023, 01, 14, 0, 1, 2) };
var actual = serializer.Serialize(testObject);

actual.TrimNewLines().Should().ContainEquivalentOf("{\"DateTime\": \"01/14/2023 00:01:02\"}");
}
}

/// <summary>
Expand Down
7 changes: 5 additions & 2 deletions YamlDotNet/Serialization/Converters/DateTimeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,22 @@ public class DateTimeConverter : IYamlTypeConverter
{
private readonly DateTimeKind kind;
private readonly IFormatProvider provider;
private readonly bool doubleQuotes;
private readonly string[] formats;

/// <summary>
/// Initializes a new instance of the <see cref="DateTimeConverter"/> class.
/// </summary>
/// <param name="kind"><see cref="DateTimeKind"/> value. Default value is <see cref="DateTimeKind.Utc"/>. <see cref="DateTimeKind.Unspecified"/> is considered as <see cref="DateTimeKind.Utc"/>.</param>
/// <param name="provider"><see cref="IFormatProvider"/> instance. Default value is <see cref="CultureInfo.InvariantCulture"/>.</param>
/// <param name="doubleQuotes">If true, will use double quotes when writing the value to the stream.</param>
/// <param name="formats">List of date/time formats for parsing. Default value is "<c>G</c>".</param>
/// <remarks>On deserializing, all formats in the list are used for conversion, while on serializing, the first format in the list is used.</remarks>
public DateTimeConverter(DateTimeKind kind = DateTimeKind.Utc, IFormatProvider? provider = null, params string[] formats)
public DateTimeConverter(DateTimeKind kind = DateTimeKind.Utc, IFormatProvider? provider = null, bool doubleQuotes = false, params string[] formats)
{
this.kind = kind == DateTimeKind.Unspecified ? DateTimeKind.Utc : kind;
this.provider = provider ?? CultureInfo.InvariantCulture;
this.doubleQuotes = doubleQuotes;
this.formats = formats.DefaultIfEmpty("G").ToArray();
}

Expand Down Expand Up @@ -91,7 +94,7 @@ public void WriteYaml(IEmitter emitter, object? value, Type type)
var adjusted = this.kind == DateTimeKind.Local ? dt.ToLocalTime() : dt.ToUniversalTime();
var formatted = adjusted.ToString(this.formats.First(), this.provider); // Always take the first format of the list.

emitter.Emit(new Scalar(AnchorName.Empty, TagName.Empty, formatted, ScalarStyle.Any, true, false));
emitter.Emit(new Scalar(AnchorName.Empty, TagName.Empty, formatted, doubleQuotes ? ScalarStyle.DoubleQuoted : ScalarStyle.Any, true, false));
}

private static DateTime EnsureDateTimeKind(DateTime dt, DateTimeKind kind)
Expand Down
1 change: 1 addition & 0 deletions YamlDotNet/Serialization/SerializerBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ public SerializerBuilder JsonCompatible()

return this
.WithTypeConverter(new GuidConverter(true), w => w.InsteadOf<GuidConverter>())
.WithTypeConverter(new DateTimeConverter(doubleQuotes: true))
.WithEventEmitter(inner => new JsonEventEmitter(inner), loc => loc.InsteadOf<TypeAssigningEventEmitter>());
}

Expand Down

0 comments on commit 306f714

Please sign in to comment.