1

I'm using ServiceStack Redis. I have an struct and I want to storage it in Redis. But when I try to get it, it always return the default value. But if I change the struct for class it works ok. Any ideas?

public struct PersonStruct
{
    public string Name { get; set; }
    public int Year { get; set; }
}

Unit test (It always pass, because redis return the default for the struct)

var obj = new PersonStruct() {Name = "SomeName", Year = 1235};
_redis.Set(key, obj, TimeSpan.FromMinutes(2));
var result = _redis.Get<PersonStruct>(key);

Assert.AreEqual(default(PersonStruct), result);
satellite satellite
  • 893
  • 2
  • 10
  • 27

2 Answers2

2

For structs you have to use custom serializer/deserializer

var obj = new PersonStruct() {Name = "SomeName", Year = 1235};
var bytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(obj));

_redis.Set(key, bytes, TimeSpan.FromMinutes(2));

var getBytes = _redis.Get(key);
var result = JsonSerializer.Deserialize<PersonStruct>(Encoding.UTF8.GetString(getBytes));

Seems it's serializing structs by calling ToString()

Greg
  • 346
  • 1
  • 10
2

The differences with Struct's is that they're treated like a single scalar value, where instead of serializing every property of a struct value, e.g. Date, Day, DayOfWeek, DayOfYear, Hour, etc in the case of a DateTime, only a single scalar value is serialized for DateTime's, TimeSpan's, etc.

ServiceStack.Text serializers does this by convention where it will attempt to use ToString() to serialize into a single string value and the TStruct(string) constructor to deserialize the value. Alternatively you can provide your own deserializer function with a static ParseJson() method.

So if you want to deserialize structs you would need to provide a serializer/deserializer for your Struct by overriding ToString() and providing a string constructor, e.g:

public struct PersonStruct
{
    public PersonStruct(string jsonStr)
    {
        var str = jsonStr.FromJson<string>();
        Year = int.Parse(str.LeftPart(','));
        Name = str.RightPart(',');
    }
        
    public string Name { get; set; }
    public int Year { get; set; }
    
    public override string ToString() => Year + "," + Name;
}

Then you'll be able to use it in ServiceStack.Redis Typed APIs as seen in this Gistlyn example gist.

mythz
  • 141,670
  • 29
  • 246
  • 390