Skip to content

Refactor DistributedCacheRateLimitStore to Use System.Text.Json Instead of Newtonsoft.Json #494

@jmbryan4

Description

@jmbryan4

The current implementation of DistributedCacheRateLimitStore uses Newtonsoft.Json for serialization and deserialization:
DistributedCacheRateLimitStore.cs

System.Text.Json is faster and more memory-efficient than Newtonsoft.Json and removes reliance on Newtonsoft.Json package, making the project more aligned with .NET’s built-in features.

Proposed Changes:

using System;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;

namespace AspNetCoreRateLimit.Store;

public class DistributedCacheRateLimitStore<T> : IRateLimitStore<T>
{
    private readonly IDistributedCache _cache;

    private static readonly JsonSerializerOptions _jsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
    };

    public DistributedCacheRateLimitStore(IDistributedCache cache)
    {
        ArgumentNullException.ThrowIfNull(cache);
        _cache = cache;
    }

    public Task SetAsync(string id, T entry, TimeSpan? expirationTime = null, CancellationToken cancellationToken = default)
    {
        var options = new DistributedCacheEntryOptions();
        if (expirationTime.HasValue)
        {
            options.SetAbsoluteExpiration(expirationTime.Value);
        }

        return _cache.SetStringAsync(id, JsonSerializer.Serialize(entry, _jsonOptions), options, cancellationToken);
    }

    public async Task<bool> ExistsAsync(string id, CancellationToken cancellationToken = default)
    {
        var stored = await _cache.GetStringAsync(id, cancellationToken);
        return !string.IsNullOrEmpty(stored);
    }

    public async Task<T> GetAsync(string id, CancellationToken cancellationToken = default)
    {
        var stored = await _cache.GetStringAsync(id, cancellationToken);
        return !string.IsNullOrEmpty(stored) ? JsonSerializer.Deserialize<T>(stored, _jsonOptions) : default;
    }

    public Task RemoveAsync(string id, CancellationToken cancellationToken = default) => _cache.RemoveAsync(id, cancellationToken);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions