Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MicroJson support for DateTimeOffset #931

Merged
merged 1 commit into from
Mar 18, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ public static string ToIso8601(DateTime dateTime)
return $"{dateTime:yyyy-MM-ddTHH:mm:ss.FFFZ}";
}

/// <summary>
/// Converts a DateTime object into an ISO 8601 string in UTC format.
/// </summary>
/// <param name="dateTime">The DateTime to convert.</param>
/// <returns>DateTime as an ISO 8601 string in UTC format.</returns>
public static string ToIso8601(DateTimeOffset dateTime)
{
return $"{dateTime:yyyy-MM-ddTHH:mm:ss.FFFZ}";
}

/// <summary>
/// Converts a DateTime to the ASP.NET Ajax JSON format.
/// </summary>
Expand All @@ -51,6 +61,16 @@ public static string ToASPNetAjax(DateTime dateTime)
return $@"\/Date({dateTime.Ticks})\/";
}

/// <summary>
/// Converts a DateTime to the ASP.NET Ajax JSON format.
/// </summary>
/// <param name="dateTime">The DateTime to convert.</param>
/// <returns>A string representation of the DateTime in ASP.NET Ajax JSON format.</returns>
public static string ToASPNetAjax(DateTimeOffset dateTime)
{
return $@"\/Date({dateTime.Ticks})\/";
}

/// <summary>
/// Converts an ASP.NET Ajax JSON string to DateTime
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System;

namespace Meadow.Foundation.Serialization;

[AttributeUsage(AttributeTargets.Property, Inherited = true)]
public class JsonIgnoreAttribute : Attribute

Check warning on line 6 in Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/JsonIgnoreAttribute.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'JsonIgnoreAttribute'
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@

namespace Meadow.Foundation.Serialization;

[AttributeUsage(AttributeTargets.Property, Inherited = true)]
public class JsonIgnoreAttribute : Attribute
{
}

public static partial class MicroJson
{
/// <summary>
Expand Down Expand Up @@ -144,7 +139,7 @@
{
var table = DeserializeString(json) as Hashtable;

return DeserializeHashtableToDictionary(table, type)

Check warning on line 142 in Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.TypeSafe.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'hashtable' in 'IDictionary? MicroJson.DeserializeHashtableToDictionary(Hashtable hashtable, Type dictionaryType)'.
?? throw new NotSupportedException($"Type '{type.Name}' not supported");
}
throw new NotSupportedException($"Type '{type.Name}' not supported");
Expand Down Expand Up @@ -278,6 +273,15 @@
Deserialize(hashtableValue, propType, ref complexInstance);
prop.SetValue(instance, complexInstance);
}
else if (propType == typeof(DateTimeOffset))
{
var dto = DateTimeOffset.Parse(values[v].ToString());
prop.SetValue(instance, dto);
}
else
{
throw new NotSupportedException($"Unable to deserialize type '{propType}'");
}
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public static partial class MicroJson
/// </summary>
/// <param name="o">The value to convert.</param>
/// <param name="dateTimeFormat">The format to use for DateTime values. Defaults to ISO 8601 format.</param>
/// <param name="convertNamesToCamelCase">True to convert all properties to camel case during serialization</param>
/// <returns>The JSON object as a string or null when the value type is not supported.</returns>
/// <remarks>For objects, only public properties with getters are converted.</remarks>
public static string? Serialize(object o, DateTimeFormat dateTimeFormat = DateTimeFormat.ISO8601, bool convertNamesToCamelCase = true)
Expand Down Expand Up @@ -79,6 +80,14 @@ public static partial class MicroJson
_ => $"\"{DateTimeConverters.ToIso8601((DateTime)o)}\"",
};
default:
if (type == typeof(DateTimeOffset))
{
return dateTimeFormat switch
{
DateTimeFormat.Ajax => $"\"{DateTimeConverters.ToASPNetAjax((DateTimeOffset)o)}\"",
_ => $"\"{DateTimeConverters.ToIso8601((DateTimeOffset)o)}\"",
};
}
if (type == typeof(Guid))
{
return $"\"{o}\"";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,54 @@
using Meadow.Foundation.Serialization;
using System;
using System.Text.Json;
using Xunit;

namespace Unit.Tests;

public class BasicTests
{
[Fact]
public void DateTimeSerializationTest()
{
var input = new DateTimeClass
{
DTField = DateTime.Now,
DTOField = DateTimeOffset.UtcNow
};

var json = MicroJson.Serialize(input);

Assert.NotNull(json);
var test = JsonSerializer.Deserialize<DateTimeClass>(json,
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
Assert.NotNull(test);
// the fraction of a second will be lost, so equality won't work
Assert.True(Math.Abs((input.DTField - test.DTField).TotalSeconds) < 1, "DateTime failed");
Assert.True(Math.Abs((input.DTOField - test.DTOField).TotalSeconds) < 1, "DateTimeOffset failed");
}

[Fact]
public void DateTimeDeserializationTest()
{
var input = new DateTimeClass
{
DTField = DateTime.Now,
DTOField = DateTimeOffset.UtcNow
};

var json = JsonSerializer.Serialize(input);

var test = MicroJson.Deserialize<DateTimeClass>(json);

Assert.NotNull(test);
// the fraction of a second will be lost, so equality won't work
Assert.True(Math.Abs((input.DTField - test.DTField).TotalSeconds) < 1, "DateTime failed");
Assert.True(Math.Abs((input.DTOField - test.DTOField).TotalSeconds) < 1, "DateTimeOffset failed");
}

[Fact]
public void SimpleIntegerPropertyTest()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,40 @@
using Meadow.Cloud;
using Meadow.Foundation.Serialization;
using Meadow.Update;
using System;
using System.Collections.Generic;
using System.Text.Json;
using Xunit;

namespace Unit.Tests;

public class CloudEntityTests
{
[Fact]
public void CloudEventSerializationTest()
{
var ce = new CloudEvent()
{
EventId = 2000,
Description = "Cloud Sample Data",
Timestamp = DateTime.UtcNow,
Measurements = new Dictionary<string, object>
{
{ "Int value", 31 },
{ "StringValue", "37-A2-0A-94-FA-42-EC-3F" }
}
};

var json = MicroJson.Serialize(ce);
Assert.NotNull(json);

var item = JsonSerializer.Deserialize<CloudEvent>(json);

Assert.NotNull(item);
// the fraction of a second will be lost, so equality won't work
Assert.True(Math.Abs((item.Timestamp - ce.Timestamp).TotalSeconds) < 1, "Timestamp failed");
}

[Fact]
public void UpdateMessageSerializationTest()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="System.Text.Json" Version="8.0.3" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
using Meadow.Foundation.Serialization;
using System;

namespace Unit.Tests;

internal class DateTimeClass
{
public DateTime DTField { get; set; }
public DateTimeOffset DTOField { get; set; }
}

internal class IntegerClass
{
public int Value { get; set; }
Expand Down
Loading