redis / redis-om-dotnet

Object mapping, and more, for Redis and .NET
MIT License
467 stars 79 forks source link

Allow overriding JsonSerializer settings #266

Open dstoyanoff opened 1 year ago

dstoyanoff commented 1 year ago

Would it be possible to allow putting custom JsonSerializerOptions when initializing the connection? That would allow everyone to control the JSON serialization in the way they want. Currently the only way to do it is via attributes on the Entity, but this isn't optimal for numerous reasons.

Is this something you would consider?

slorello89 commented 1 year ago

Hi @dstoyanoff - I'll leave this open to see if anyone else runs into this problem, FWIW there are some seralizers that Redis OM needs to use to make sure things like GeoLocs and dates work correctly, so doing something like this could have a great deal of undefined behavior.

dstoyanoff commented 1 year ago

You could also expose some subset of settings that people can override, while maintaining the core configuration compatible with redis.

Twinki14 commented 1 year ago

Bumping this as I've been trying to use NodaTime in my entities / documents

Currently I'm unable to use NodaTime in combination with this framework, I can't add the needed JsonConverters to the SerializerSettings that this framework uses as there isn't any way to override or even add to the SerializerSettings this framework uses

Even trying to use the JsonConverter attribute leads me no-where, and even then I'd be limited to using attributes everywhere. Major downside to this framework if we can't access the SerializerSettings this framework is using, especially considering it's function

mohammed-ehsan commented 1 year ago

I've faced a similar issue. I was trying to use the slicing feature of json arrays supported by ReJson. For example, I can do something like: json.get <key> .property_array[1:4:1]. With RedisOM's default json serializer options, it was failing. RedisOM internal json serializer options omits empty arrays; thus, deserialized objects had null arrays. I've had to create something like this that I use for inserts:

public static async Task JsonSetAsync<TRedisModel>(this IRedisConnection connection, string key, TRedisModel model)
        where TRedisModel : IRedisModel
    {
        await connection.ExecuteAsync("JSON.SET", 
            key, 
            ".", 
            JsonSerializer.Serialize(model, CustomJsonSerializationOptions.RedisOptions));
    }

And this is how I fetch data:

public async Task<IEnumerable<T>> Seek<T>(TId sourceId, int skip, int take,
        Expression<Func<TRedisLinkedModel, IEnumerable<T>>> collection)
    {
        var key = _idStrategy.Construct(sourceId);
        int endIndexExclusive = skip + take;
        string jsonPath;
        try
        {
            jsonPath = collection.GetRedisJsonPath();
        }
        catch (InvalidOperationException)
        {
            throw new InvalidCollectionPathException($"Invalid collection path for type {typeof(TRedisLinkedModel).Name}");
        }

        var skipString = skip.ToString();
        var endIndexExclusiveString = endIndexExclusive.ToString();
        var paginatedJsonPath = $"{jsonPath}[{skipString}:{endIndexExclusiveString}:1]";

        var result = await Connection.ExecuteAsync("JSON.GET", key, paginatedJsonPath);

        var deserializedResult = JsonSerializer.Deserialize<IEnumerable<T>>(result, CustomJsonSerializationOptions.RedisOptions);
        return deserializedResult;
    }

Worth mentioning, I'm working with a special case where I've created an internal package on top of RedisOM for the organization.

goodstas commented 11 months ago

Hi, @slorello89 . I'm also looking for a way to define my custom JsonSerializerOptions. I'm working with NetTopologySuite library and the properties of my business objects include types like Point and Polygon of NetTopologySuite. Currently i got an error while saving them in Redis. So what can i do?