redis-om-dotnet icon indicating copy to clipboard operation
redis-om-dotnet copied to clipboard

`FirstOrDefault` throws `JsonException` when field contains a JSON String

Open lucamuscat opened this issue 2 years ago • 3 comments

Currently, If one were to retrieve a Hash document that contains a string field with JSON data, FindById or Where(...).FirstOrDefault will throw a JsonException.

Code to reproduce bug:

using Redis.OM;
using Redis.OM.Modeling;
using System.Text.Json;

var connectionProvider = new RedisConnectionProvider("redis://127.0.0.1:6379");
connectionProvider.Connection.CreateIndex(typeof(Dummy));
var dummyContext = connectionProvider.RedisCollection<Dummy>();

var inputData = new Dictionary<string, string>();
inputData.Add("test", "item");
string serializedDict = JsonSerializer.Serialize(inputData);

dummyContext.Insert(new Dummy() { id = "hello", dictAsJson = serializedDict });

var item = dummyContext.Where(x => x.id == "hello").FirstOrDefault(); // Throws JSONException

[Document]
public class Dummy
{
    [RedisIdField]
    [Indexed]
    public string id { get; set; } = String.Empty;
    public string dictAsJson { get; set; } = String.Empty;
}

Reported Exception:

System.Text.Json.JsonException: ''t' is invalid after a value. Expected either ',', '}', or ']'. Path: $ | LineNumber: 0 | BytePositionInLine: 30.'

Proof that data is stored in Redis: image

Is this a bug, or did I make a mistake along the way?

Thanks and Regards

lucamuscat avatar Aug 16 '22 11:08 lucamuscat

No this looks like a bug, the Hash serializer/deserializer is meant to work on very flat objects, it's not really anticipating the insertion of json data in the fields, and under the covers, all the hash deserializer is doing is building a JSON object in memory from the hash and using that construction to deserialize it back into the object. This is something I can look into, but I think my recommendation would be to try to change the type to JSON, unless there's some compelling reason not to, the serializers json uses are more sophisticated than the serializer I wrote for hashes for sure. If I change the storage type to JSON, it seems to work.

slorello89 avatar Aug 16 '22 12:08 slorello89

Thanks for the reply.

Swapping to a DocumentType of JSON works.

This seems like quite a dangerous bug--taking into consideration that Hash is the default DocumentType and JSON strings may easily be injected.

lucamuscat avatar Aug 16 '22 13:08 lucamuscat

Thanks for the reply.

Swapping to a DocumentType of JSON works.

This seems like quite a dangerous bug--taking into consideration that Hash is the default DocumentType and JSON strings may easily be injected.

Json is your best bet. If you want to use the older hash tables to store json, maybe you can look at StackExchange.Redis.Extensions which has various serialization packages that allow the seemless serialization / deserialization to the redis HashSet types.

VagyokC4 avatar Aug 16 '22 22:08 VagyokC4

Going to close this one out - IMO if you have JSON, using JSON serialization is your best bet.

slorello89 avatar May 03 '23 11:05 slorello89