Skip to content

Commit

Permalink
Added serialization support for Try and Unit (#168)
Browse files Browse the repository at this point in the history
  • Loading branch information
petrkoutnycz authored Aug 23, 2024
2 parents 408c4d9 + 0a3d6c7 commit 72395dd
Show file tree
Hide file tree
Showing 11 changed files with 340 additions and 8 deletions.
1 change: 0 additions & 1 deletion src/FuncSharp.Benchmarks/FuncSharp.Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<Nullable>enable</Nullable>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
<LangVersion>10</LangVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion src/FuncSharp.Examples/FuncSharp.Examples.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>10</LangVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion src/FuncSharp.Tests/FuncSharp.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>CS1591</NoWarn>
<IsPackable>false</IsPackable>
<LangVersion>10</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FsCheck.Xunit" Version="2.16.6" />
Expand Down
70 changes: 70 additions & 0 deletions src/FuncSharp.Tests/Product/UnitJsonConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System.Text.Json;
using Xunit;

namespace FuncSharp.Tests;

public class UnitJsonConverterTests
{
private record DummyObjectWithUnit(string PropertyBefore, Unit Unit, string PropertyAfter);

[Fact]
public void Serializes_unit_only()
{
// Act
var json = JsonSerializer.Serialize(Unit.Value);

// Assert
Assert.Equal("{}", json);
}

[Fact]
public void Deserializes_unit_only()
{
// Act
var value = JsonSerializer.Deserialize<Unit>("{}");

// Assert
Assert.Equal(Unit.Value, value);
}

[Fact]
public void Serializes_complex_object_including_unit()
{
// Arrange
var value = new DummyObjectWithUnit("before", Unit.Value, "after");

// Act
var json = JsonSerializer.Serialize(value);

// Assert
Assert.Equal(@"{""PropertyBefore"":""before"",""Unit"":{},""PropertyAfter"":""after""}", json);
}

[Fact]
public void Deserializes_complex_object_including_unit()
{
// Arrange
var json = @"{""PropertyBefore"":""before"",""Unit"":{},""PropertyAfter"":""after""}";

// Act
var value = JsonSerializer.Deserialize<DummyObjectWithUnit>(json);

// Assert
Assert.Equal("before", value.PropertyBefore);
Assert.Equal(Unit.Value, value.Unit);
Assert.Equal("after", value.PropertyAfter);
}

[Fact]
public void Serializes_try_with_success_as_unit()
{
// Arrange
var value = Try.Success<Unit, string>(Unit.Value);

// Act
var json = JsonSerializer.Serialize(value);

// Assert
Assert.Equal(@"{""IsSuccess"":true,""Value"":{}}", json);
}
}
121 changes: 121 additions & 0 deletions src/FuncSharp.Tests/Try/TryConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System.Text.Json;
using Xunit;

namespace FuncSharp.Tests;

public class TryConverterTests
{
private sealed record DummySuccess(string SomeProperty);
private sealed record DummyError(string Message);

private sealed record ComplexObject(string PropertyBefore, Try<DummySuccess, DummyError> Value, string PropertyAfter);

[Fact]
public void Serializes_success_with_primitive_value()
{
// Arrange
var value = Try.Success<int, string>(42);

// Act
var json = JsonSerializer.Serialize(value);

// Assert
Assert.Equal(@"{""IsSuccess"":true,""Value"":42}", json);
}

[Fact]
public void Deserializes_success_with_primitive_value()
{
// Arrange
var json = @"{""IsSuccess"":true,""Value"":42}";

// Act
var value = JsonSerializer.Deserialize<Try<int, string>>(json);

// Assert
Assert.True(value.IsSuccess);
Assert.Equal(42, value.Success.Get());
}

[Fact]
public void Serializes_success_with_reference_type()
{
// Arrange
var value = Try.Success<DummySuccess, string>(new DummySuccess("success!"));

// Act
var json = JsonSerializer.Serialize(value);

// Assert
Assert.Equal(@"{""IsSuccess"":true,""Value"":{""SomeProperty"":""success!""}}", json);
}

[Fact]
public void Deserializes_success_with_reference_type()
{
// Arrange
var json = @"{""IsSuccess"":true,""Value"":{""SomeProperty"":""success!""}}";

// Act
var value = JsonSerializer.Deserialize<Try<DummySuccess, string>>(json);

// Assert
Assert.True(value.IsSuccess);
Assert.Equal(new DummySuccess("success!"), value.Success.Get());
}

[Fact]
public void Serializes_error_with_primitive_value()
{
// Arrange
var value = Try.Error<int, string>("error!");

// Act
var json = JsonSerializer.Serialize(value);

// Assert
Assert.Equal(@"{""IsSuccess"":false,""Value"":""error!""}", json);
}

[Fact]
public void Serializes_error_with_reference_type()
{
// Arrange
var value = Try.Error<int, DummyError>(new DummyError("error!"));

// Act
var json = JsonSerializer.Serialize(value);

// Assert
Assert.Equal(@"{""IsSuccess"":false,""Value"":{""Message"":""error!""}}", json);
}

[Fact]
public void Serializes_complex_object_including_try()
{
// Arrange
var value = new ComplexObject("before", Try.Success<DummySuccess, DummyError>(new DummySuccess("success!")), "after");

// Act
var json = JsonSerializer.Serialize(value);

// Assert
Assert.Equal(@"{""PropertyBefore"":""before"",""Value"":{""IsSuccess"":true,""Value"":{""SomeProperty"":""success!""}},""PropertyAfter"":""after""}", json);
}

[Fact]
public void Deserializes_complex_object_including_try()
{
// Arrange
var json = @"{""PropertyBefore"":""before"",""Value"":{""IsSuccess"":true,""Value"":{""SomeProperty"":""success!""}},""PropertyAfter"":""after""}";

// Act
var value = JsonSerializer.Deserialize<ComplexObject>(json);

// Assert
Assert.Equal("before", value.PropertyBefore);
Assert.True(value.Value.IsSuccess);
Assert.Equal(new DummySuccess("success!"), value.Value.Success.Get());
Assert.Equal("after", value.PropertyAfter);
}
}
9 changes: 4 additions & 5 deletions src/FuncSharp/FuncSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>CS1591</NoWarn>
<Version>10.0.0</Version>
<AssemblyVersion>10.0.0</AssemblyVersion>
<FileVersion>10.0.0</FileVersion>
<Version>10.0.1</Version>
<AssemblyVersion>10.0.1</AssemblyVersion>
<FileVersion>10.0.1</FileVersion>
<PackageId>FuncSharp</PackageId>
<Description>A C# library with main purpose to reduce boilerplate code and avoid bugs thanks to stronger typing. Utilizes many concepts from functional programming languages that are also applicable in C#. Originally written by Honza Široký.</Description>
<Authors>Mews, Honza Široký</Authors>
Expand All @@ -13,7 +13,7 @@
<PackageProjectUrl>https://github.com/MewsSystems/FuncSharp</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageReleaseNotes>Upgraded target .NET version to 8.0</PackageReleaseNotes>
<PackageReleaseNotes>Added JsonConverter implementations for Try&lt;,&gt; and Unit types</PackageReleaseNotes>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/MewsSystems/FuncSharp</RepositoryUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
Expand All @@ -22,7 +22,6 @@
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>10</LangVersion>
<Product>FuncSharp</Product>
<PackageReadmeFile>readme.md</PackageReadmeFile>
</PropertyGroup>
Expand Down
3 changes: 3 additions & 0 deletions src/FuncSharp/Product/Unit.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@

using System.Text.Json.Serialization;

namespace FuncSharp;

/// <summary>
/// The Unit type (product of zero types). It has only one instance.
/// </summary>
[JsonConverter(typeof(UnitJsonConverter))]
public sealed class Unit : Product0
{
private Unit()
Expand Down
20 changes: 20 additions & 0 deletions src/FuncSharp/Product/UnitJsonConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace FuncSharp;

public sealed class UnitJsonConverter : JsonConverter<Unit>
{
public override Unit Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
reader.Read();
return Unit.Value;
}

public override void Write(Utf8JsonWriter writer, Unit value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteEndObject();
}
}
1 change: 1 addition & 0 deletions src/FuncSharp/Try/Try.cs
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,7 @@ private static bool IsOrContainsOperationCanceledException(this Exception except
}
}

[System.Text.Json.Serialization.JsonConverterAttribute(typeof(TryConverterFactory))]
public struct Try<TSuccess, TError> : IEquatable<Try<TSuccess, TError>>
{
public Try(TSuccess success)
Expand Down
1 change: 1 addition & 0 deletions src/FuncSharp/Try/Try.tt
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ public static class Try
}
}

[System.Text.Json.Serialization.JsonConverterAttribute(typeof(TryConverterFactory))]
public struct Try<TSuccess, TError> : IEquatable<Try<TSuccess, TError>>
{
public Try(TSuccess success)
Expand Down
Loading

0 comments on commit 72395dd

Please sign in to comment.