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
22 changes: 6 additions & 16 deletions YamlDotNet/Serialization/Converters/DateOnlyConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace YamlDotNet.Serialization.Converters
/// <summary>
/// This represents the YAML converter entity for <see cref="DateOnly"/>.
/// </summary>
public class DateOnlyConverter : IYamlTypeConverter
public class DateOnlyConverter : ScalarConverterBase<DateOnly>
{
private readonly IFormatProvider provider;
private readonly bool doubleQuotes;
Expand All @@ -52,16 +52,6 @@ public DateOnlyConverter(IFormatProvider? provider = null, bool doubleQuotes = f
this.formats = formats.DefaultIfEmpty("d").ToArray();
}

/// <summary>
/// Gets a value indicating whether the current converter supports converting the specified type.
/// </summary>
/// <param name="type"><see cref="Type"/> to check.</param>
/// <returns>Returns <c>True</c>, if the current converter supports; otherwise returns <c>False</c>.</returns>
public bool Accepts(Type type)
{
return type == typeof(DateOnly);
}

/// <summary>
/// Reads an object's state from a YAML parser.
/// </summary>
Expand All @@ -70,9 +60,9 @@ public bool Accepts(Type type)
/// <param name="rootDeserializer">The deserializer to use to deserialize complex types.</param>
/// <returns>Returns the <see cref="DateOnly"/> instance converted.</returns>
/// <remarks>On deserializing, all formats in the list are used for conversion.</remarks>
public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
public override object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
var value = parser.Consume<Scalar>().Value;
var value = ConsumeScalarValue(parser);

var dateOnly = DateOnly.ParseExact(value, this.formats, this.provider);
return dateOnly;
Expand All @@ -86,12 +76,12 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
/// <param name="type"><see cref="Type"/> to convert.</param>
/// <param name="serializer">The root serializer that can be used to serialize complex types.</param>
/// <remarks>On serializing, the first format in the list is used.</remarks>
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
var dateOnly = (DateOnly)value!;
var formatted = dateOnly.ToString(this.formats.First(), this.provider); // Always take the first format of the list.
var formatted = dateOnly.ToString(this.formats.First(), this.provider);

emitter.Emit(new Scalar(AnchorName.Empty, TagName.Empty, formatted, doubleQuotes ? ScalarStyle.DoubleQuoted : ScalarStyle.Any, true, false));
EmitScalar(emitter, formatted, doubleQuotes ? ScalarStyle.DoubleQuoted : ScalarStyle.Any);
}
}
}
Expand Down
20 changes: 5 additions & 15 deletions YamlDotNet/Serialization/Converters/DateTime8601Converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace YamlDotNet.Serialization.Converters
/// <summary>
/// This represents the YAML converter entity for <see cref="DateTime"/> using the ISO-8601 standard format.
/// </summary>
public class DateTime8601Converter : IYamlTypeConverter
public class DateTime8601Converter : ScalarConverterBase<DateTime>
{
private readonly ScalarStyle scalarStyle;

Expand All @@ -49,16 +49,6 @@ public DateTime8601Converter(ScalarStyle scalarStyle)
this.scalarStyle = scalarStyle;
}

/// <summary>
/// Gets a value indicating whether the current converter supports converting the specified type.
/// </summary>
/// <param name="type"><see cref="Type"/> to check.</param>
/// <returns>Returns <c>True</c>, if the current converter supports; otherwise returns <c>False</c>.</returns>
public bool Accepts(Type type)
{
return type == typeof(DateTime);
}

/// <summary>
/// Reads an object's state from a YAML parser.
/// </summary>
Expand All @@ -67,9 +57,9 @@ public bool Accepts(Type type)
/// <param name="rootDeserializer">The deserializer to use to deserialize complex types.</param>
/// <returns>Returns the <see cref="DateTime"/> instance converted.</returns>
/// <remarks>On deserializing, all formats in the list are used for conversion.</remarks>
public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
public override object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
var value = parser.Consume<Scalar>().Value;
var value = ConsumeScalarValue(parser);
var result = DateTime.ParseExact(value, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);

return result;
Expand All @@ -83,11 +73,11 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
/// <param name="type"><see cref="Type"/> to convert.</param>
/// <param name="serializer">A serializer to serializer complext objects.</param>
/// <remarks>On serializing, the first format in the list is used.</remarks>
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
var formatted = ((DateTime)value!).ToString("O", CultureInfo.InvariantCulture);

emitter.Emit(new Scalar(AnchorName.Empty, TagName.Empty, formatted, scalarStyle, true, false));
EmitScalar(emitter, formatted, scalarStyle);
}
}
}
22 changes: 6 additions & 16 deletions YamlDotNet/Serialization/Converters/DateTimeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace YamlDotNet.Serialization.Converters
/// <summary>
/// This represents the YAML converter entity for <see cref="DateTime"/>.
/// </summary>
public class DateTimeConverter : IYamlTypeConverter
public class DateTimeConverter : ScalarConverterBase<DateTime>
{
private readonly DateTimeKind kind;
private readonly IFormatProvider provider;
Expand All @@ -54,16 +54,6 @@ public DateTimeConverter(DateTimeKind kind = DateTimeKind.Utc, IFormatProvider?
this.formats = formats.DefaultIfEmpty("G").ToArray();
}

/// <summary>
/// Gets a value indicating whether the current converter supports converting the specified type.
/// </summary>
/// <param name="type"><see cref="Type"/> to check.</param>
/// <returns>Returns <c>True</c>, if the current converter supports; otherwise returns <c>False</c>.</returns>
public bool Accepts(Type type)
{
return type == typeof(DateTime);
}

/// <summary>
/// Reads an object's state from a YAML parser.
/// </summary>
Expand All @@ -72,9 +62,9 @@ public bool Accepts(Type type)
/// <param name="rootDeserializer">The deserializer to use to deserialize complex types.</param>
/// <returns>Returns the <see cref="DateTime"/> instance converted.</returns>
/// <remarks>On deserializing, all formats in the list are used for conversion.</remarks>
public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
public override object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
var value = parser.Consume<Scalar>().Value;
var value = ConsumeScalarValue(parser);
var style = this.kind == DateTimeKind.Local ? DateTimeStyles.AssumeLocal : DateTimeStyles.AssumeUniversal;

var dt = DateTime.ParseExact(value, this.formats, this.provider, style);
Expand All @@ -90,13 +80,13 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
/// <param name="type"><see cref="Type"/> to convert.</param>
/// <param name="serializer">A serializer to serializer complext objects.</param>
/// <remarks>On serializing, the first format in the list is used.</remarks>
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
var dt = (DateTime)value!;
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.
var formatted = adjusted.ToString(this.formats.First(), this.provider);

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

private static DateTime EnsureDateTimeKind(DateTime dt, DateTimeKind kind)
Expand Down
22 changes: 6 additions & 16 deletions YamlDotNet/Serialization/Converters/DateTimeOffsetConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace YamlDotNet.Serialization.Converters
/// To use this converter, call WithTypeConverter(new DateTimeOffsetConverter()) on the
/// <seealso cref="DeserializerBuilder"/> or <seealso cref="SerializerBuilder"/>.
/// </summary>
public class DateTimeOffsetConverter : IYamlTypeConverter
public class DateTimeOffsetConverter : ScalarConverterBase<DateTimeOffset>
{
private readonly IFormatProvider provider;
private readonly ScalarStyle style;
Expand All @@ -59,16 +59,6 @@ public DateTimeOffsetConverter(
this.formats = formats.DefaultIfEmpty("O").ToArray();
}

/// <summary>
/// Gets a value indicating whether the current converter supports converting the specified type.
/// </summary>
/// <param name="type"><see cref="Type"/> to check.</param>
/// <returns>Returns <c>True</c>, if the current converter supports; otherwise returns <c>False</c>.</returns>
public bool Accepts(Type type)
{
return type == typeof(DateTimeOffset);
}

/// <summary>
/// Reads an object's state from a YAML parser.
/// </summary>
Expand All @@ -77,9 +67,9 @@ public bool Accepts(Type type)
/// <param name="rootDeserializer">The deserializer to use to deserialize complex types.</param>
/// <returns>Returns the <see cref="DateTime"/> instance converted.</returns>
/// <remarks>On deserializing, all formats in the list are used for conversion.</remarks>
public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
public override object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
var value = parser.Consume<Scalar>().Value;
var value = ConsumeScalarValue(parser);
var result = DateTimeOffset.ParseExact(value, formats, provider, dateStyle);

return result;
Expand All @@ -93,12 +83,12 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
/// <param name="type"><see cref="Type"/> to convert.</param>
/// <param name="serializer">A serializer to serializer complext objects.</param>
/// <remarks>On serializing, the first format in the list is used.</remarks>
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
var dt = (DateTimeOffset)value!;
var formatted = dt.ToString(formats.First(), this.provider); // Always take the first format of the list.
var formatted = dt.ToString(formats.First(), this.provider);

emitter.Emit(new Scalar(AnchorName.Empty, TagName.Empty, formatted, style, true, false));
EmitScalar(emitter, formatted, style);
}
}
}
63 changes: 63 additions & 0 deletions YamlDotNet/Serialization/Converters/ScalarConverterBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// This file is part of YamlDotNet - A .NET library for YAML.
// Copyright (c) Antoine Aubry and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;

namespace YamlDotNet.Serialization.Converters
{
/// <summary>
/// Base class for YAML type converters that handle a single scalar type.
/// Provides common functionality for type acceptance, scalar consumption, and emission.
/// </summary>
/// <typeparam name="T">The type this converter handles.</typeparam>
public abstract class ScalarConverterBase<T> : IYamlTypeConverter
{
/// <inheritdoc/>
public bool Accepts(Type type)
{
return type == typeof(T);
}

/// <inheritdoc/>
public abstract object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer);

/// <inheritdoc/>
public abstract void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer);

/// <summary>
/// Consumes and returns the scalar value from the parser.
/// </summary>
protected static string ConsumeScalarValue(IParser parser)
{
return parser.Consume<Scalar>().Value;
}

/// <summary>
/// Emits a scalar value with the specified style.
/// </summary>
protected static void EmitScalar(IEmitter emitter, string formatted, ScalarStyle style)
{
emitter.Emit(new Scalar(AnchorName.Empty, TagName.Empty, formatted, style, true, false));
}
}
}
22 changes: 6 additions & 16 deletions YamlDotNet/Serialization/Converters/TimeOnlyConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace YamlDotNet.Serialization.Converters
/// <summary>
/// This represents the YAML converter entity for <see cref="TimeOnly"/>.
/// </summary>
public class TimeOnlyConverter : IYamlTypeConverter
public class TimeOnlyConverter : ScalarConverterBase<TimeOnly>
{
private readonly IFormatProvider provider;
private readonly bool doubleQuotes;
Expand All @@ -52,16 +52,6 @@ public TimeOnlyConverter(IFormatProvider? provider = null, bool doubleQuotes = f
this.formats = formats.DefaultIfEmpty("T").ToArray();
}

/// <summary>
/// Gets a value indicating whether the current converter supports converting the specified type.
/// </summary>
/// <param name="type"><see cref="Type"/> to check.</param>
/// <returns>Returns <c>True</c>, if the current converter supports; otherwise returns <c>False</c>.</returns>
public bool Accepts(Type type)
{
return type == typeof(TimeOnly);
}

/// <summary>
/// Reads an object's state from a YAML parser.
/// </summary>
Expand All @@ -70,9 +60,9 @@ public bool Accepts(Type type)
/// <param name="rootDeserializer">The deserializer to use to deserialize complex types.</param>
/// <returns>Returns the <see cref="TimeOnly"/> instance converted.</returns>
/// <remarks>On deserializing, all formats in the list are used for conversion.</remarks>
public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
public override object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
var value = parser.Consume<Scalar>().Value;
var value = ConsumeScalarValue(parser);

var timeOnly = TimeOnly.ParseExact(value, this.formats, this.provider);
return timeOnly;
Expand All @@ -86,12 +76,12 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
/// <param name="type"><see cref="Type"/> to convert.</param>
/// <param name="serializer">A serializer to serializer complext objects.</param>
/// <remarks>On serializing, the first format in the list is used.</remarks>
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
var timeOnly = (TimeOnly)value!;
var formatted = timeOnly.ToString(this.formats.First(), this.provider); // Always take the first format of the list.
var formatted = timeOnly.ToString(this.formats.First(), this.provider);

emitter.Emit(new Scalar(AnchorName.Empty, TagName.Empty, formatted, doubleQuotes ? ScalarStyle.DoubleQuoted : ScalarStyle.Any, true, false));
EmitScalar(emitter, formatted, doubleQuotes ? ScalarStyle.DoubleQuoted : ScalarStyle.Any);
}
}
}
Expand Down
16 changes: 11 additions & 5 deletions YamlDotNet/Serialization/EventEmitters/JsonEventEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

using System;
using System.Globalization;
using System.Text.RegularExpressions;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization.NamingConventions;
Expand Down Expand Up @@ -87,26 +86,33 @@ public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter)

case TypeCode.Single:
var floatValue = (float)value;
eventInfo.RenderedValue = floatValue.ToString("G", CultureInfo.InvariantCulture);
if (float.IsNaN(floatValue) || float.IsInfinity(floatValue))
{
eventInfo.RenderedValue = floatValue.ToString(CultureInfo.InvariantCulture);
eventInfo.Style = ScalarStyle.DoubleQuoted;
}
else
{
eventInfo.RenderedValue = formatter.FormatNumber(floatValue);
}

break;

case TypeCode.Double:
var doubleValue = (double)value;
eventInfo.RenderedValue = doubleValue.ToString("G", CultureInfo.InvariantCulture);
if (double.IsNaN(doubleValue) || double.IsInfinity(doubleValue))
{
eventInfo.RenderedValue = doubleValue.ToString(CultureInfo.InvariantCulture);
eventInfo.Style = ScalarStyle.DoubleQuoted;
}
else
{
eventInfo.RenderedValue = formatter.FormatNumber(doubleValue);
}
break;

case TypeCode.Decimal:
var decimalValue = (decimal)value;
eventInfo.RenderedValue = decimalValue.ToString(CultureInfo.InvariantCulture);
eventInfo.RenderedValue = formatter.FormatNumber(value);
break;

case TypeCode.String:
Expand Down
Loading