Skip to content

Commit

Permalink
Add JsonConverter for converting entity to/from JSON
Browse files Browse the repository at this point in the history
  • Loading branch information
Jakub Berthoty authored and satano committed Nov 26, 2019
1 parent 8ee8642 commit 3eaeb19
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
47 changes: 47 additions & 0 deletions src/Converters/JsonConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Kros.Utils;
using System;
using System.Text.Json;

namespace Kros.KORM.Converter
{
/// <summary>
/// Converter for converting JSON value from DB to entity.
/// </summary>
/// <seealso cref="IConverter" />
public class JsonConverter<T> : IConverter
{
private readonly JsonSerializerOptions _options;

/// <summary>
/// Initializes a new instance of the <see cref="JsonConverter{T}"/> class with default serialization options.
/// </summary>
public JsonConverter() : this(new JsonSerializerOptions())
{ }

/// <summary>
/// Initializes a new instance of the <see cref="JsonConverter{T}"/> class.
/// </summary>
/// <param name="options">Serialization options.</param>
/// <exception cref="ArgumentNullException">The value of <paramref name="options"/> is null.</exception>
public JsonConverter(JsonSerializerOptions options)
{
_options = Check.NotNull(options, nameof(options));
}

/// <summary>
/// Converts specified JSON value from DB to entity.
/// </summary>
/// <param name="value">JSON value.</param>
/// <returns>Entity.</returns>
public object Convert(object value)
=> JsonSerializer.Deserialize((string)value, typeof(T), _options);

/// <summary>
/// Converts entity to JSON value for DB.
/// </summary>
/// <param name="value">Entity.</param>
/// <returns>Converted JSON value for DB.</returns>
public object ConvertBack(object value)
=> JsonSerializer.Serialize(value, typeof(T), _options);
}
}
1 change: 1 addition & 0 deletions src/Kros.KORM.Extensions.Asp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.2.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="System.Text.Json" Version="4.6.0" />
</ItemGroup>

<ItemGroup>
Expand Down
127 changes: 127 additions & 0 deletions tests/Converters/JsonConverterShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
using FluentAssertions;
using Kros.KORM.Converter;
using System;
using System.Text.Json;
using System.Text.RegularExpressions;
using Xunit;

namespace Kros.KORM.Extensions.Api.UnitTests.Converters
{
public class JsonConverterShould
{
[Fact]
public void ThrowArgumentExceptionWhenSerializationOptionsAreNull()
{
Action action = () => new JsonConverter<TestClass>(null);

action.Should().Throw<ArgumentException>();
}

[Fact]
public void ConvertJsonToEntity()
{
var converter = new JsonConverter<TestClass>();

TestClass expected = GetSampleClass();
var actual = converter.Convert(GetSampleJson());

actual.Should().BeOfType(typeof(TestClass));
((TestClass)actual).Should().BeEquivalentTo(expected);
}

[Fact]
public void ThrowJsonExceptionWhenTryingToConvertImproperlyFormattedJsonToEntity()
{
var converter = new JsonConverter<TestClass>();

Action action = () => converter.Convert(GetSampleImproperlyFormattedJson());

action.Should().Throw<JsonException>();
}

[Fact]
public void ConvertImproperlyFormattedJsonToEntityWhenUsingCorrectOptions()
{
var converter = new JsonConverter<TestClass>(new JsonSerializerOptions()
{
AllowTrailingCommas = true,
PropertyNameCaseInsensitive = true
});

TestClass expected = GetSampleClass();
var actual = converter.Convert(GetSampleImproperlyFormattedJson());

actual.Should().BeOfType(typeof(TestClass));
((TestClass)actual).Should().BeEquivalentTo(expected);
}

[Fact]
public void ConvertEntityToJson()
{
var converter = new JsonConverter<TestClass>();

string expected = GetSampleJson();
var actual = converter.ConvertBack(GetSampleClass());

actual.Should().BeOfType(typeof(string));
((string)actual).Should().Equals(expected);
}

private TestClass GetSampleClass()
=> new TestClass()
{
BoolProperty = true,
StringProperty = "LoremIpsum",
DoubleProperty = Math.PI,
ArrayProperty = new int[] { 4, 8, 15, 16, 23, 42 },
ObjectProperty = new TestClass() { StringProperty = "DolorSitAmet" }
};

private string GetSampleJson()
=> Regex.Replace(
@"{
""BoolProperty"":true,
""StringProperty"":""LoremIpsum"",
""DoubleProperty"":3.1415926535897931,
""ArrayProperty"":[4,8,15,16,23,42],
""ObjectProperty"":
{
""BoolProperty"":false,
""StringProperty"":""DolorSitAmet"",
""DoubleProperty"":0,
""ArrayProperty"":null,
""ObjectProperty"":null
}
}", @"\s+", "");

private string GetSampleImproperlyFormattedJson()
=> Regex.Replace(
@"{
""boolProperty"":true,
""stringProperty"":""LoremIpsum"",
""doubleProperty"":3.1415926535897931,
""arrayProperty"":[4,8,15,16,23,42],
""objectProperty"":
{
""boolProperty"":false,
""stringProperty"":""DolorSitAmet"",
""doubleProperty"":0,
""arrayProperty"":null,
""objectProperty"":null
},
}", @"\s+", "");

private class TestClass
{
public bool BoolProperty { get; set; }

public string StringProperty { get; set; }

public double DoubleProperty { get; set; }

public int[] ArrayProperty { get; set; }

public TestClass ObjectProperty { get; set; }
}
}
}

0 comments on commit 3eaeb19

Please sign in to comment.