sqids / sqids-dotnet

Official .NET port of Sqids. Generate short unique IDs from numbers.

Home Page:https://sqids.org/dotnet

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Do you have example of using this with a custom JSON converter?

grosch-intl opened this issue · comments

I'm using minimal API with .NET 7 and I wanted to add an attribute to my ID fields so that when the JSON encoding/decoding happens, it automatically runs it through this library. The issue I'm having is that when I call builder.Services.ConfigureHttpJsonOptions there's not an IServiceProvider available to pass to the custom converter, meaning it doesn't have access to the injected SqidsEncoder.

I'm wanting to do something like this:

public sealed class SqidJsonConverter : JsonConverter<int> {
    public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
        if (reader.GetString() is not string encoded)
            throw new JsonException();

        return options
            .GetServiceProvider()
            .GetRequiredService<SqidsEncoder<int>>()
            .Decode(encoded)
            .FirstOrDefault();
    }

    public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) {
        var sqid = options.GetServiceProvider().GetRequiredService<SqidsEncoder<int>>();

        writer.WriteStringValue(sqid.Encode(value));
    }
}

How about creating a singleton SqidsEncoder manually?

    var opt = configuration.GetSection("Sqid").Get<CustomSqidOption>();
    var encoder = new SqidsEncoder<int>(new SqidsOptions() { MinLength = opt.MinLength, Alphabet = opt.Alphabet });
    services.AddSingleton(encoder);
    builder.Services.ConfigureHttpJsonOptions(opt =>
    {
        opt.SerializerOptions.Converters.Add(new SqidJsonConverter(encoder));
    });

public sealed class SqidJsonConverter(SqidsEncoder<int> encoder) : JsonConverter<int>
{
    public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.GetString() is not string encoded)
            throw new JsonException();

        return encoder.Decode(encoded).FirstOrDefault();
    }

    public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(encoder.Encode(value));
    }
}