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

feat: allow for specifying custom json serialization #78

Merged
merged 4 commits into from
Jul 10, 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
18 changes: 18 additions & 0 deletions LitRedis.Core/Builders/LitRedisServiceCollectionBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Text.Json;
using LitRedis.Core.Implementations;
using LitRedis.Core.Interfaces;
using LitRedis.Core.Models;
Expand All @@ -11,11 +12,15 @@ public class LitRedisServiceCollectionBuilder
{
public IServiceCollection ServiceCollection { get; }
private readonly LitRedisOptions _litRedisOptions = new();
private readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);

public LitRedisServiceCollectionBuilder(IServiceCollection serviceCollection)
{
ServiceCollection = serviceCollection;

serviceCollection.TryAddSingleton(_litRedisOptions);
serviceCollection.TryAddSingleton<ILitRedisJsonSerializer, LitRedisSystemTextJsonSerializer>();
serviceCollection.TryAddSingleton<ILitRedisSystemTextJsonOptionsProvider>(new DefaultLitRedisSystemTextJsonOptionsProvider(_jsonOptions));
serviceCollection.TryAddSingleton<ILitRedisConnection, LitLitRedisConnection>();
serviceCollection.TryAddScoped<ILitRedisConnectionService, LitRedisConnectionService>();
}
Expand Down Expand Up @@ -43,4 +48,17 @@ public LitRedisServiceCollectionBuilder WithLitRedisOptions(Action<LitRedisOptio
configure(_litRedisOptions);
return this;
}

public LitRedisServiceCollectionBuilder WithJsonSerializer<T>() where T : class, ILitRedisJsonSerializer
{
ServiceCollection.RemoveAll<ILitRedisJsonSerializer>();
ServiceCollection.TryAddSingleton<ILitRedisJsonSerializer, T>();
return this;
}

public LitRedisServiceCollectionBuilder WithJsonOptions(Action<JsonSerializerOptions> configure)
{
configure(_jsonOptions);
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Text.Json;
using LitRedis.Core.Interfaces;

namespace LitRedis.Core.Implementations;

public class DefaultLitRedisSystemTextJsonOptionsProvider(JsonSerializerOptions options)
: ILitRedisSystemTextJsonOptionsProvider
{
public JsonSerializerOptions GetOptions() => options;
}
13 changes: 8 additions & 5 deletions LitRedis.Core/Implementations/LitRedisCacheStore.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using LitRedis.Core.Interfaces;
Expand All @@ -14,11 +13,15 @@ public class LitRedisCacheStore : ILitRedisCacheStore
{
private readonly IMemoryCache _cache;
private readonly ILitRedisConnectionService _litRedisConnectionService;
private readonly ILitRedisJsonSerializer _jsonSerializer;

public LitRedisCacheStore(IMemoryCache cache, ILitRedisConnectionService litRedisConnectionService)
public LitRedisCacheStore(IMemoryCache cache,
ILitRedisConnectionService litRedisConnectionService,
ILitRedisJsonSerializer jsonSerializer)
{
_cache = cache;
_litRedisConnectionService = litRedisConnectionService;
_jsonSerializer = jsonSerializer;
}

private static void KeyGuard(string key)
Expand All @@ -43,9 +46,9 @@ public async Task PutAsync<T>(string key, T model, TimeSpan? expiry, Cancellatio
return;
}

var str = JsonSerializer.Serialize(model);
var json = _jsonSerializer.Serialize(model);

await _litRedisConnectionService.UseDbAsync((db, _) => db.StringSetAsync(key, str, expiry), cancellationToken);
await _litRedisConnectionService.UseDbAsync((db, _) => db.StringSetAsync(key, json, expiry), cancellationToken);
}

/// <inheritdoc />
Expand All @@ -57,7 +60,7 @@ public async Task<T> GetAsync<T>(string key, CancellationToken cancellationToken

var str = await GetAsync(key, cancellationToken);

return string.IsNullOrWhiteSpace(str) ? default : JsonSerializer.Deserialize<T>(str);
return string.IsNullOrWhiteSpace(str) ? default : _jsonSerializer.Deserialize<T>(str);
}

/// <inheritdoc />
Expand Down
18 changes: 18 additions & 0 deletions LitRedis.Core/Implementations/LitRedisSystemTextJsonSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Text.Json;
using LitRedis.Core.Interfaces;

namespace LitRedis.Core.Implementations;

public class LitRedisSystemTextJsonSerializer : ILitRedisJsonSerializer
{
private readonly ILitRedisSystemTextJsonOptionsProvider _optionsProvider;

public LitRedisSystemTextJsonSerializer(ILitRedisSystemTextJsonOptionsProvider optionsProvider)
{
_optionsProvider = optionsProvider;
}

public string Serialize<T>(T value) => JsonSerializer.Serialize(value, _optionsProvider.GetOptions());

public T Deserialize<T>(string value) => JsonSerializer.Deserialize<T>(value, _optionsProvider.GetOptions());
}
8 changes: 8 additions & 0 deletions LitRedis.Core/Interfaces/ILitRedisJsonSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace LitRedis.Core.Interfaces;

public interface ILitRedisJsonSerializer
{
string Serialize<T>(T value);

T Deserialize<T>(string value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.Json;

namespace LitRedis.Core.Interfaces;

public interface ILitRedisSystemTextJsonOptionsProvider
{
JsonSerializerOptions GetOptions();
}
2 changes: 1 addition & 1 deletion LitRedis.Core/LitRedis.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Version>4.0.3</Version>
<Version>4.0.4</Version>
<LangVersion>latestmajor</LangVersion>
</PropertyGroup>

Expand Down
3 changes: 2 additions & 1 deletion LitRedis.Core/ServiceProviderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ namespace LitRedis.Core;
//todo: test
public static class ServiceProviderExtensions
{
public static IServiceCollection AddLitRedis(this IServiceCollection serviceCollection,
public static IServiceCollection AddLitRedis(
this IServiceCollection serviceCollection,
Action<LitRedisServiceCollectionBuilder> configure)
{
var builder = new LitRedisServiceCollectionBuilder(serviceCollection);
Expand Down
5 changes: 4 additions & 1 deletion LitRedis.Sample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ private static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefau
.ConfigureServices((_, services) =>
{
services
.AddLitRedis(redis => redis.WithCaching().WithLocking().WithConnectionString("localhost:6379,defaultDatabase=0"))
.AddLitRedis(redis => redis
.WithCaching()
.WithLocking()
.WithConnectionString("localhost:6379,defaultDatabase=0"))
.AddHostedService<SampleHostedService>()
.AddLogging(o => o.AddSimpleConsole(c => c.TimestampFormat = "[yyy-MM-dd HH:mm:ss] "));
});
Expand Down
47 changes: 47 additions & 0 deletions LitRedis.Tests/Core/Implementations/JsonSerializationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Drawing;
using System.Dynamic;
using System.Text.Json;
using FluentAssertions;
using LitRedis.Core.Builders;
using LitRedis.Core.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace LitRedis.Tests.Core.Implementations;

internal class SampleClass
{
public string Name { get; set; }
public int Age { get; set; }
public ExpandoObject Custom { get; set; }
}

[TestClass]
public class JsonSerializationTests
{
[TestMethod]
public void Json_Serializer_Should_Handle_Expando()
{
dynamic custom = new ExpandoObject();
custom.Color = "Red";
custom.Size = "Large";

var sample = new SampleClass
{
Name = "John Doe",
Age = 30,
Custom = custom
};

var sp = new LitRedisServiceCollectionBuilder(new ServiceCollection()).ServiceCollection.BuildServiceProvider();
var options = sp.GetRequiredService<ILitRedisSystemTextJsonOptionsProvider>().GetOptions();
var serialized = JsonSerializer.Serialize(sample, options);
var deserialized = JsonSerializer.Deserialize<SampleClass>(serialized, options);
var serializedAgain = JsonSerializer.Serialize(deserialized, options);
serializedAgain.Should()
.Be("{\"name\":\"John Doe\",\"age\":30,\"custom\":{\"Color\":\"Red\",\"Size\":\"Large\"}}");
dynamic c = deserialized.Custom;
string color = c.Color.ToString();
color.Should().Be("Red");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public async Task Lit_Redis_Cache_Store_Should_Get_Value_Object()

var mockRedisConnectionService = fixture.Freeze<Mock<ILitRedisConnectionService>>();

fixture.Inject<ILitRedisJsonSerializer>(new LitRedisSystemTextJsonSerializer(new DefaultLitRedisSystemTextJsonOptionsProvider(new JsonSerializerOptions(JsonSerializerDefaults.Web))));

mockRedisConnectionService.Setup(x =>
x.UseDbAsync(It.IsAny<Func<IDatabase, CancellationToken, Task<RedisValue>>>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new RedisValue(JsonSerializer.Serialize(cacheValue)));
Expand Down
Loading